1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef C2PARAM_H_
18#define C2PARAM_H_
19
20#include <C2.h>
21
22#include <stdbool.h>
23#include <stdint.h>
24
25#include <algorithm>
26#include <list>
27#include <string>
28#include <type_traits>
29
30#define C2_PACK __attribute__((packed))
31
32namespace android {
33
34/// \addtogroup Parameters
35/// @{
36
37/// \defgroup internal Internal helpers.
38
39/*!
40 * \file
41 * PARAMETERS: SETTINGs, TUNINGs, and INFOs
42 * ===
43 *
44 * These represent miscellaneous control and metadata information and are likely copied into
45 * kernel space. Therefore, these are C-like structures designed to carry just a small amount of
46 * information. We are using C++ to be able to add constructors, as well as non-virtual and class
47 * methods.
48 *
49 * ==Specification details:
50 *
51 * Restrictions:
52 *   - must be POD struct, e.g. no vtable (no virtual destructor)
53 *   - must have the same size in 64-bit and 32-bit mode (no size_t)
54 *   - as such, no pointer members
55 *
56 * Behavior:
57 * - Params can be global (not related to input or output), related to input or output,
58 *   or related to an input/output stream.
59 * - All params are queried/set using a unique param index, which incorporates a potential stream
60 *   index and/or port.
61 * - Querying (supported) params MUST never fail.
62 * - All params MUST have default values.
63 * - If some fields have "unsupported" or "invalid" values during setting, this SHOULD be
64 *   communicated to the app.
65 *   a) Ideally, this should be avoided.  When setting parameters, in general, component should do
66 *     "best effort" to apply all settings. It should change "invalid/unsupported" values to the
67 *     nearest supported values.
68 *   - This is communicated to the client by changing the source values in tune()/
69 *     configure().
70 *   b) If falling back to a supported value is absolutely impossible, the component SHALL return
71 *     an error for the specific setting, but should continue to apply other settings.
72 *     TODO: this currently may result in unintended results.
73 *
74 * **NOTE:** unlike OMX, params are not versioned. Instead, a new struct with new base index
75 * SHALL be added as new versions are required.
76 *
77 * The proper subtype (Setting, Info or Param) is incorporated into the class type. Define structs
78 * to define multiple subtyped versions of related parameters.
79 *
80 * ==Implementation details:
81 *
82 * - Use macros to define parameters
83 * - All parameters must have a default constructor
84 *   - This is only used for instantiating the class in source (e.g. will not be used
85 *     when building a parameter by the framework from key/value pairs.)
86 */
87
88/// \ingroup internal
89struct _C2ParamManipulator;
90
91/**
92 * Parameter base class.
93 */
94struct C2Param {
95    // param index encompasses the following:
96    //
97    // - type (setting, tuning, info, struct)
98    // - vendor extension flag
99    // - flexible parameter flag
100    // - direction (global, input, output)
101    // - stream flag
102    // - stream ID (usually 0)
103    //
104    // layout:
105    //
106    //      +------+-----+---+------+--------+----|------+--------------+
107    //      | kind | dir | - |stream|streamID|flex|vendor|  base index  |
108    //      +------+-----+---+------+--------+----+------+--------------+
109    //  bit: 31..30 29.28       25   24 .. 17  16    15   14    ..     0
110    //
111public:
112    /**
113     * C2Param kinds, usable as bitmaps.
114     */
115    enum Kind : uint32_t {
116        NONE    = 0,
117        STRUCT  = (1 << 0),
118        INFO    = (1 << 1),
119        SETTING = (1 << 2),
120        TUNING  = (1 << 3) | SETTING, // tunings are settings
121    };
122
123    /**
124     * base index (including the vendor extension bit) is a global index for
125     * C2 parameter structs. (e.g. the same indices cannot be reused for different
126     * structs for different components).
127     */
128    struct BaseIndex {
129    protected:
130        enum : uint32_t {
131            kTypeMask      = 0xC0000000,
132            kTypeStruct    = 0x00000000,
133            kTypeTuning    = 0x40000000,
134            kTypeSetting   = 0x80000000,
135            kTypeInfo      = 0xC0000000,
136
137            kDirMask       = 0x30000000,
138            kDirGlobal     = 0x20000000,
139            kDirUndefined  = 0x30000000, // MUST have all bits set
140            kDirInput      = 0x00000000,
141            kDirOutput     = 0x10000000,
142
143            kStreamFlag    = 0x02000000,
144            kStreamIdMask  = 0x01FE0000,
145            kStreamIdShift = 17,
146            kStreamIdMax   = kStreamIdMask >> kStreamIdShift,
147            kStreamMask    = kStreamFlag | kStreamIdMask,
148
149            kFlexibleFlag  = 0x00010000,
150            kVendorFlag    = 0x00008000,
151            kParamMask     = 0x0000FFFF,
152            kBaseMask      = kParamMask | kFlexibleFlag,
153        };
154
155    public:
156        enum : uint32_t {
157            kVendorStart = kVendorFlag, ///< vendor structs SHALL start after this
158            _kFlexibleFlag = kFlexibleFlag, // TODO: this is only needed for testing
159        };
160
161        /// constructor/conversion from uint32_t
162        inline BaseIndex(uint32_t index) : mIndex(index) { }
163
164        // no conversion from uint64_t
165        inline BaseIndex(uint64_t index) = delete;
166
167        /// returns true iff this is a vendor extension parameter
168        inline bool isVendor() const { return mIndex & kVendorFlag; }
169
170        /// returns true iff this is a flexible parameter (with variable size)
171        inline bool isFlexible() const { return mIndex & kFlexibleFlag; }
172
173        /// returns the base type: the index for the underlying struct
174        inline unsigned int baseIndex() const { return mIndex & kBaseMask; }
175
176        /// returns the param index for the underlying struct
177        inline unsigned int paramIndex() const { return mIndex & kParamMask; }
178
179        DEFINE_FIELD_BASED_COMPARISON_OPERATORS(BaseIndex, mIndex)
180
181    protected:
182        uint32_t mIndex;
183    };
184
185    /**
186     * type encompasses the parameter kind (tuning, setting, info), whether the
187     * parameter is global, input or output, and whether it is for a stream.
188     */
189    struct Type : public BaseIndex {
190        /// returns true iff this is a global parameter (not for input nor output)
191        inline bool isGlobal() const { return (mIndex & kDirMask) == kDirGlobal; }
192        /// returns true iff this is an input or input stream parameter
193        inline bool forInput() const { return (mIndex & kDirMask) == kDirInput; }
194        /// returns true iff this is an output or output stream parameter
195        inline bool forOutput() const { return (mIndex & kDirMask) == kDirOutput; }
196
197        /// returns true iff this is a stream parameter
198        inline bool forStream() const { return mIndex & kStreamFlag; }
199        /// returns true iff this is a port (input or output) parameter
200        inline bool forPort() const   { return !forStream() && !isGlobal(); }
201
202        /// returns the parameter type: the parameter index without the stream ID
203        inline uint32_t type() const { return mIndex & (~kStreamIdMask); }
204
205        /// return the kind of this param
206        inline Kind kind() const {
207            switch (mIndex & kTypeMask) {
208                case kTypeStruct: return STRUCT;
209                case kTypeInfo: return INFO;
210                case kTypeSetting: return SETTING;
211                case kTypeTuning: return TUNING;
212                default: return NONE; // should not happen
213            }
214        }
215
216        /// constructor/conversion from uint32_t
217        inline Type(uint32_t index) : BaseIndex(index) { }
218
219        // no conversion from uint64_t
220        inline Type(uint64_t index) = delete;
221
222    private:
223        friend struct C2Param;   // for setPort()
224        friend struct C2Tuning;  // for kTypeTuning
225        friend struct C2Setting; // for kTypeSetting
226        friend struct C2Info;    // for kTypeInfo
227        // for kDirGlobal
228        template<typename T, typename S, int I, class F> friend struct C2GlobalParam;
229        template<typename T, typename S, int I, class F> friend struct C2PortParam;   // for kDir*
230        template<typename T, typename S, int I, class F> friend struct C2StreamParam; // for kDir*
231        friend struct _C2ParamInspector; // for testing
232
233        /**
234         * Sets the port/stream direction.
235         * @return true on success, false if could not set direction (e.g. it is global param).
236         */
237        inline bool setPort(bool output) {
238            if (isGlobal()) {
239                return false;
240            } else {
241                mIndex = (mIndex & ~kDirMask) | (output ? kDirOutput : kDirInput);
242                return true;
243            }
244        }
245    };
246
247    /**
248     * index encompasses all remaining information: basically the stream ID.
249     */
250    struct Index : public Type {
251        /// returns the index as uint32_t
252        inline operator uint32_t() const { return mIndex; }
253
254        /// constructor/conversion from uint32_t
255        inline Index(uint32_t index) : Type(index) { }
256
257        // no conversion from uint64_t
258        inline Index(uint64_t index) = delete;
259
260        /// returns the stream ID or ~0 if not a stream
261        inline unsigned stream() const {
262            return forStream() ? rawStream() : ~0U;
263        }
264
265    private:
266        friend struct C2Param;           // for setStream, makeStreamId, isValid
267        friend struct _C2ParamInspector; // for testing
268
269        /**
270         * @return true if the type is valid, e.g. direction is not undefined AND
271         * stream is 0 if not a stream param.
272         */
273        inline bool isValid() const {
274            // there is no Type::isValid (even though some of this check could be
275            // performed on types) as this is only used on index...
276            return (forStream() ? rawStream() < kStreamIdMax : rawStream() == 0)
277                    && (mIndex & kDirMask) != kDirUndefined;
278        }
279
280        /// returns the raw stream ID field
281        inline unsigned rawStream() const {
282            return (mIndex & kStreamIdMask) >> kStreamIdShift;
283        }
284
285        /// returns the streamId bitfield for a given |stream|. If stream is invalid,
286        /// returns an invalid bitfield.
287        inline static uint32_t makeStreamId(unsigned stream) {
288            // saturate stream ID (max value is invalid)
289            if (stream > kStreamIdMax) {
290                stream = kStreamIdMax;
291            }
292            return (stream << kStreamIdShift) & kStreamIdMask;
293        }
294
295        /**
296         * Sets the stream index.
297         * \return true on success, false if could not set index (e.g. not a stream param).
298         */
299        inline bool setStream(unsigned stream) {
300            if (forStream()) {
301                mIndex = (mIndex & ~kStreamIdMask) | makeStreamId(stream);
302                return this->stream() < kStreamIdMax;
303            }
304            return false;
305        }
306    };
307
308public:
309    // public getters for Index methods
310
311    /// returns true iff this is a vendor extension parameter
312    inline bool isVendor() const { return _mIndex.isVendor(); }
313    /// returns true iff this is a flexible parameter
314    inline bool isFlexible() const { return _mIndex.isFlexible(); }
315    /// returns true iff this is a global parameter (not for input nor output)
316    inline bool isGlobal() const { return _mIndex.isGlobal(); }
317    /// returns true iff this is an input or input stream parameter
318    inline bool forInput() const { return _mIndex.forInput(); }
319    /// returns true iff this is an output or output stream parameter
320    inline bool forOutput() const { return _mIndex.forOutput(); }
321
322    /// returns true iff this is a stream parameter
323    inline bool forStream() const { return _mIndex.forStream(); }
324    /// returns true iff this is a port (input or output) parameter
325    inline bool forPort() const   { return _mIndex.forPort(); }
326
327    /// returns the stream ID or ~0 if not a stream
328    inline unsigned stream() const { return _mIndex.stream(); }
329
330    /// returns the parameter type: the parameter index without the stream ID
331    inline uint32_t type() const { return _mIndex.type(); }
332
333    /// returns the kind of this parameter
334    inline Kind kind() const { return _mIndex.kind(); }
335
336    /// returns the size of the parameter or 0 if the parameter is invalid
337    inline size_t size() const { return _mSize; }
338
339    /// returns true iff the parameter is valid
340    inline operator bool() const { return _mIndex.isValid() && _mSize > 0; }
341
342    /// returns true iff the parameter is invalid
343    inline bool operator!() const { return !operator bool(); }
344
345    // equality is done by memcmp (use equals() to prevent any overread)
346    inline bool operator==(const C2Param &o) const {
347        return equals(o) && memcmp(this, &o, _mSize) == 0;
348    }
349    inline bool operator!=(const C2Param &o) const { return !operator==(o); }
350
351    /// safe(r) type cast from pointer and size
352    inline static C2Param* From(void *addr, size_t len) {
353        // _mSize must fit into size
354        if (len < sizeof(_mSize) + offsetof(C2Param, _mSize)) {
355            return nullptr;
356        }
357        // _mSize must match length
358        C2Param *param = (C2Param*)addr;
359        if (param->_mSize != len) {
360            return nullptr;
361        }
362        return param;
363    }
364
365#if 0
366    template<typename P, class=decltype(C2Param(P()))>
367    P *As() { return P::From(this); }
368    template<typename P>
369    const P *As() const { return const_cast<const P*>(P::From(const_cast<C2Param*>(this))); }
370#endif
371
372protected:
373    /// sets the stream field. Returns true iff successful.
374    inline bool setStream(unsigned stream) {
375        return _mIndex.setStream(stream);
376    }
377
378    /// sets the port (direction). Returns true iff successful.
379    inline bool setPort(bool output) {
380        return _mIndex.setPort(output);
381    }
382
383public:
384    /// invalidate this parameter. There is no recovery from this call; e.g. parameter
385    /// cannot be 'corrected' to be valid.
386    inline void invalidate() { _mSize = 0; }
387
388    // if other is the same kind of (valid) param as this, copy it into this and return true.
389    // otherwise, do not copy anything, and return false.
390    inline bool updateFrom(const C2Param &other) {
391        if (other._mSize == _mSize && other._mIndex == _mIndex && _mSize > 0) {
392            memcpy(this, &other, _mSize);
393            return true;
394        }
395        return false;
396    }
397
398protected:
399    // returns |o| if it is a null ptr, or if can suitably be a param of given |type| (e.g. has
400    // same type (ignoring stream ID), and size). Otherwise, returns null. If |checkDir| is false,
401    // allow undefined or different direction (e.g. as constructed from C2PortParam() vs.
402    // C2PortParam::input), but still require equivalent type (stream, port or global); otherwise,
403    // return null.
404    inline static const C2Param* ifSuitable(
405            const C2Param* o, size_t size, Type type, size_t flexSize = 0, bool checkDir = true) {
406        if (o == nullptr || o->_mSize < size || (flexSize && ((o->_mSize - size) % flexSize))) {
407            return nullptr;
408        } else if (checkDir) {
409            return o->_mIndex.type() == type.mIndex ? o : nullptr;
410        } else if (o->_mIndex.isGlobal()) {
411            return nullptr;
412        } else {
413            return ((o->_mIndex.type() ^ type.mIndex) & ~Type::kDirMask) ? nullptr : o;
414        }
415    }
416
417    /// base constructor
418    inline C2Param(uint32_t paramSize, Index paramIndex)
419        : _mSize(paramSize),
420          _mIndex(paramIndex) {
421        if (paramSize > sizeof(C2Param)) {
422            memset(this + 1, 0, paramSize - sizeof(C2Param));
423        }
424    }
425
426    /// base constructor with stream set
427    inline C2Param(uint32_t paramSize, Index paramIndex, unsigned stream)
428        : _mSize(paramSize),
429          _mIndex(paramIndex | Index::makeStreamId(stream)) {
430        if (paramSize > sizeof(C2Param)) {
431            memset(this + 1, 0, paramSize - sizeof(C2Param));
432        }
433        if (!forStream()) {
434            invalidate();
435        }
436    }
437
438private:
439    friend struct _C2ParamInspector; // for testing
440
441    /// returns the base type: the index for the underlying struct (for testing
442    /// as this can be gotten by the baseIndex enum)
443    inline uint32_t _baseIndex() const { return _mIndex.baseIndex(); }
444
445    /// returns true iff |o| has the same size and index as this. This performs the
446    /// basic check for equality.
447    inline bool equals(const C2Param &o) const {
448        return _mSize == o._mSize && _mIndex == o._mIndex;
449    }
450
451    uint32_t _mSize;
452    Index _mIndex;
453};
454
455/// \ingroup internal
456/// allow C2Params access to private methods, e.g. constructors
457#define C2PARAM_MAKE_FRIENDS \
458    template<typename U, typename S, int I, class F> friend struct C2GlobalParam; \
459    template<typename U, typename S, int I, class F> friend struct C2PortParam; \
460    template<typename U, typename S, int I, class F> friend struct C2StreamParam; \
461
462/**
463 * Setting base structure for component method signatures. Wrap constructors.
464 */
465struct C2Setting : public C2Param {
466protected:
467    template<typename ...Args>
468    inline C2Setting(const Args(&... args)) : C2Param(args...) { }
469public: // TODO
470    enum : uint32_t { indexFlags = Type::kTypeSetting };
471};
472
473/**
474 * Tuning base structure for component method signatures. Wrap constructors.
475 */
476struct C2Tuning : public C2Setting {
477protected:
478    template<typename ...Args>
479    inline C2Tuning(const Args(&... args)) : C2Setting(args...) { }
480public: // TODO
481    enum : uint32_t { indexFlags = Type::kTypeTuning };
482};
483
484/**
485 * Info base structure for component method signatures. Wrap constructors.
486 */
487struct C2Info : public C2Param {
488protected:
489    template<typename ...Args>
490    inline C2Info(const Args(&... args)) : C2Param(args...) { }
491public: // TODO
492    enum : uint32_t { indexFlags = Type::kTypeInfo };
493};
494
495/**
496 * Structure uniquely specifying a field in an arbitrary structure.
497 *
498 * \note This structure is used differently in C2FieldDescriptor to
499 * identify array fields, such that _mSize is the size of each element. This is
500 * because the field descriptor contains the array-length, and we want to keep
501 * a relevant element size for variable length arrays.
502 */
503struct _C2FieldId {
504//public:
505    /**
506     * Constructor used for C2FieldDescriptor that removes the array extent.
507     *
508     * \param[in] offset pointer to the field in an object at address 0.
509     */
510    template<typename T, class B=typename std::remove_extent<T>::type>
511    inline _C2FieldId(T* offset)
512        : // offset is from "0" so will fit on 32-bits
513          _mOffset((uint32_t)(uintptr_t)(offset)),
514          _mSize(sizeof(B)) { }
515
516    /**
517     * Direct constructor from offset and size.
518     *
519     * \param[in] offset offset of the field.
520     * \param[in] size size of the field.
521     */
522    inline _C2FieldId(size_t offset, size_t size)
523        : _mOffset(offset), _mSize(size) {}
524
525    /**
526     * Constructor used to identify a field in an object.
527     *
528     * \param U[type] pointer to the object that contains this field. This is needed in case the
529     *        field is in an (inherited) base class, in which case T will be that base class.
530     * \param pm[im] member pointer to the field
531     */
532    template<typename R, typename T, typename U, typename B=typename std::remove_extent<R>::type>
533    inline _C2FieldId(U *, R T::* pm)
534        : _mOffset((uint32_t)(uintptr_t)(&(((U*)256)->*pm)) - 256u),
535          _mSize(sizeof(B)) { }
536
537    /**
538     * Constructor used to identify a field in an object.
539     *
540     * \param U[type] pointer to the object that contains this field
541     * \param pm[im] member pointer to the field
542     */
543    template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
544    inline _C2FieldId(R T::* pm)
545        : _mOffset((uint32_t)(uintptr_t)(&(((T*)0)->*pm))),
546          _mSize(sizeof(B)) { }
547
548    inline bool operator==(const _C2FieldId &other) const {
549        return _mOffset == other._mOffset && _mSize == other._mSize;
550    }
551
552    inline bool operator<(const _C2FieldId &other) const {
553        return _mOffset < other._mOffset ||
554            // NOTE: order parent structure before sub field
555            (_mOffset == other._mOffset && _mSize > other._mSize);
556    }
557
558    DEFINE_OTHER_COMPARISON_OPERATORS(_C2FieldId)
559
560#if 0
561    inline uint32_t offset() const { return _mOffset; }
562    inline uint32_t size() const { return _mSize; }
563#endif
564
565#if defined(FRIEND_TEST)
566    friend void PrintTo(const _C2FieldId &d, ::std::ostream*);
567#endif
568
569private:
570    uint32_t _mOffset; // offset of field
571    uint32_t _mSize;   // size of field
572};
573
574/**
575 * Structure uniquely specifying a field in a configuration
576 */
577struct C2ParamField {
578//public:
579    // TODO: fix what this is for T[] (for now size becomes T[1])
580    template<typename S, typename T>
581    inline C2ParamField(S* param, T* offset)
582        : _mIndex(param->index()),
583          _mFieldId(offset) {}
584
585    template<typename R, typename T, typename U>
586    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
587
588    inline bool operator==(const C2ParamField &other) const {
589        return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
590    }
591
592    inline bool operator<(const C2ParamField &other) const {
593        return _mIndex < other._mIndex ||
594            (_mIndex == other._mIndex && _mFieldId < other._mFieldId);
595    }
596
597    DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
598
599private:
600    C2Param::Index _mIndex;
601    _C2FieldId _mFieldId;
602};
603
604/**
605 * A shared (union) representation of numeric values
606 */
607class C2Value {
608public:
609    /// A union of supported primitive types.
610    union Primitive {
611        int32_t  i32;   ///< int32_t value
612        uint32_t u32;   ///< uint32_t value
613        int64_t  i64;   ///< int64_t value
614        uint64_t u64;   ///< uint64_t value
615        float    fp;    ///< float value
616
617        // constructors - implicit
618        Primitive(int32_t value)  : i32(value) { }
619        Primitive(uint32_t value) : u32(value) { }
620        Primitive(int64_t value)  : i64(value) { }
621        Primitive(uint64_t value) : u64(value) { }
622        Primitive(float value)    : fp(value)  { }
623
624        Primitive() : u64(0) { }
625
626    private:
627        friend class C2Value;
628        template<typename T> const T &ref() const;
629    };
630
631    enum Type {
632        NO_INIT,
633        INT32,
634        UINT32,
635        INT64,
636        UINT64,
637        FLOAT,
638    };
639
640    template<typename T> static constexpr Type typeFor();
641
642    // constructors - implicit
643    template<typename T>
644    C2Value(T value)  : mType(typeFor<T>()),  mValue(value) { }
645
646    C2Value() : mType(NO_INIT) { }
647
648    inline Type type() const { return mType; }
649
650    template<typename T>
651    inline bool get(T *value) const {
652        if (mType == typeFor<T>()) {
653            *value = mValue.ref<T>();
654            return true;
655        }
656        return false;
657    }
658
659private:
660    Type mType;
661    Primitive mValue;
662};
663
664template<> const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
665template<> const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; }
666template<> const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; }
667template<> const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; }
668template<> const float &C2Value::Primitive::ref<float>() const { return fp; }
669
670template<> constexpr C2Value::Type C2Value::typeFor<int32_t>() { return INT32; }
671template<> constexpr C2Value::Type C2Value::typeFor<int64_t>() { return INT64; }
672template<> constexpr C2Value::Type C2Value::typeFor<uint32_t>() { return UINT32; }
673template<> constexpr C2Value::Type C2Value::typeFor<uint64_t>() { return UINT64; }
674template<> constexpr C2Value::Type C2Value::typeFor<float>() { return FLOAT; }
675
676/**
677 * field descriptor. A field is uniquely defined by an index into a parameter.
678 * (Note: Stream-id is not captured as a field.)
679 *
680 * Ordering of fields is by offset. In case of structures, it is depth first,
681 * with a structure taking an index just before and in addition to its members.
682 */
683struct C2FieldDescriptor {
684//public:
685    /** field types and flags
686     * \note: only 32-bit and 64-bit fields are supported (e.g. no boolean, as that
687     * is represented using INT32).
688     */
689    enum Type : uint32_t {
690        // primitive types
691        INT32   = C2Value::INT32,  ///< 32-bit signed integer
692        UINT32  = C2Value::UINT32, ///< 32-bit unsigned integer
693        INT64   = C2Value::INT64,  ///< 64-bit signed integer
694        UINT64  = C2Value::UINT64, ///< 64-bit signed integer
695        FLOAT   = C2Value::FLOAT,  ///< 32-bit floating point
696
697        // array types
698        STRING = 0x100, ///< fixed-size string (POD)
699        BLOB,           ///< blob. Blobs have no sub-elements and can be thought of as byte arrays;
700                        ///< however, bytes cannot be individually addressed by clients.
701
702        // complex types
703        STRUCT_FLAG = 0x10000, ///< structs. Marked with this flag in addition to their baseIndex.
704    };
705
706    typedef std::pair<C2String, C2Value::Primitive> named_value_type;
707    typedef std::vector<const named_value_type> named_values_type;
708    //typedef std::pair<std::vector<C2String>, std::vector<C2Value::Primitive>> named_values_type;
709
710    /**
711     * Template specialization that returns the named values for a type.
712     *
713     * \todo hide from client.
714     *
715     * \return a vector of name-value pairs.
716     */
717    template<typename B>
718    static named_values_type namedValuesFor(const B &);
719
720    inline C2FieldDescriptor(uint32_t type, uint32_t length, C2StringLiteral name, size_t offset, size_t size)
721        : _mType((Type)type), _mLength(length), _mName(name), _mFieldId(offset, size) { }
722
723    template<typename T, class B=typename std::remove_extent<T>::type>
724    inline C2FieldDescriptor(const T* offset, const char *name)
725        : _mType(this->getType((B*)nullptr)),
726          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
727          _mName(name),
728          _mNamedValues(namedValuesFor(*(B*)0)),
729          _mFieldId(offset) {}
730
731/*
732    template<typename T, typename B=typename std::remove_extent<T>::type>
733    inline C2FieldDescriptor<T, B, false>(T* offset, const char *name)
734        : _mType(this->getType((B*)nullptr)),
735          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
736          _mName(name),
737          _mFieldId(offset) {}
738*/
739
740    /// \deprecated
741    template<typename T, typename S, class B=typename std::remove_extent<T>::type>
742    constexpr inline C2FieldDescriptor(S*, T S::* field, const char *name)
743        : _mType(this->getType((B*)nullptr)),
744          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
745          _mName(name),
746          _mFieldId(&(((S*)0)->*field)) {}
747
748    /// returns the type of this field
749    inline Type type() const { return _mType; }
750    /// returns the length of the field in case it is an array. Returns 0 for
751    /// T[] arrays, returns 1 for T[1] arrays as well as if the field is not an array.
752    inline size_t length() const { return _mLength; }
753    /// returns the name of the field
754    inline C2StringLiteral name() const { return _mName; }
755
756    const named_values_type &namedValues() const { return _mNamedValues; }
757
758#if defined(FRIEND_TEST)
759    friend void PrintTo(const C2FieldDescriptor &, ::std::ostream*);
760    friend bool operator==(const C2FieldDescriptor &, const C2FieldDescriptor &);
761    FRIEND_TEST(C2ParamTest_ParamFieldList, VerifyStruct);
762#endif
763
764private:
765    const Type _mType;
766    const uint32_t _mLength; // the last member can be arbitrary length if it is T[] array,
767                       // extending to the end of the parameter (this is marked with
768                       // 0). T[0]-s are not fields.
769    const C2StringLiteral _mName;
770    const named_values_type _mNamedValues;
771
772    const _C2FieldId _mFieldId;   // field identifier (offset and size)
773
774    // NOTE: We do not capture default value(s) here as that may depend on the component.
775    // NOTE: We also do not capture bestEffort, as 1) this should be true for most fields,
776    // 2) this is at parameter granularity.
777
778    // type resolution
779    inline static Type getType(int32_t*)  { return INT32; }
780    inline static Type getType(uint32_t*) { return UINT32; }
781    inline static Type getType(int64_t*)  { return INT64; }
782    inline static Type getType(uint64_t*) { return UINT64; }
783    inline static Type getType(float*)    { return FLOAT; }
784    inline static Type getType(char*)     { return STRING; }
785    inline static Type getType(uint8_t*)  { return BLOB; }
786
787    template<typename T,
788             class=typename std::enable_if<std::is_enum<T>::value>::type>
789    inline static Type getType(T*) {
790        typename std::underlying_type<T>::type underlying(0);
791        return getType(&underlying);
792    }
793
794    // verify C2Struct by having a fieldList and a baseIndex.
795    template<typename T,
796             class=decltype(T::baseIndex + 1), class=decltype(T::fieldList)>
797    inline static Type getType(T*) {
798        static_assert(!std::is_base_of<C2Param, T>::value, "cannot use C2Params as fields");
799        return (Type)(T::baseIndex | STRUCT_FLAG);
800    }
801};
802
803#define DEFINE_NO_NAMED_VALUES_FOR(type) \
804template<> inline C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const type &) { \
805    return named_values_type(); \
806}
807
808// We cannot subtype constructor for enumerated types so insted define no named values for
809// non-enumerated integral types.
810DEFINE_NO_NAMED_VALUES_FOR(int32_t)
811DEFINE_NO_NAMED_VALUES_FOR(uint32_t)
812DEFINE_NO_NAMED_VALUES_FOR(int64_t)
813DEFINE_NO_NAMED_VALUES_FOR(uint64_t)
814DEFINE_NO_NAMED_VALUES_FOR(uint8_t)
815DEFINE_NO_NAMED_VALUES_FOR(char)
816DEFINE_NO_NAMED_VALUES_FOR(float)
817
818/**
819 * Describes the fields of a structure.
820 */
821struct C2StructDescriptor {
822public:
823    /// Returns the parameter type
824    inline C2Param::BaseIndex baseIndex() const { return _mType.baseIndex(); }
825
826    // Returns the number of fields in this param (not counting any recursive fields).
827    // Must be at least 1 for valid params.
828    inline size_t numFields() const { return _mFields.size(); }
829
830    // Returns the list of immediate fields (not counting any recursive fields).
831    typedef std::vector<const C2FieldDescriptor>::const_iterator field_iterator;
832    inline field_iterator cbegin() const { return _mFields.cbegin(); }
833    inline field_iterator cend() const { return _mFields.cend(); }
834
835    // only supplying const iterator - but these are needed for range based loops
836    inline field_iterator begin() const { return _mFields.cbegin(); }
837    inline field_iterator end() const { return _mFields.cend(); }
838
839    template<typename T>
840    inline C2StructDescriptor(T*)
841        : C2StructDescriptor(T::baseIndex, T::fieldList) { }
842
843    inline C2StructDescriptor(
844            C2Param::BaseIndex type,
845            std::initializer_list<const C2FieldDescriptor> fields)
846        : _mType(type), _mFields(fields) { }
847
848private:
849    const C2Param::BaseIndex _mType;
850    const std::vector<const C2FieldDescriptor> _mFields;
851};
852
853/**
854 * Describes parameters for a component.
855 */
856struct C2ParamDescriptor {
857public:
858    /**
859     * Returns whether setting this param is required to configure this component.
860     * This can only be true for builtin params for platform-defined components (e.g. video and
861     * audio encoders/decoders, video/audio filters).
862     * For vendor-defined components, it can be true even for vendor-defined params,
863     * but it is not recommended, in case the component becomes platform-defined.
864     */
865    inline bool isRequired() const { return _mIsRequired; }
866
867    /**
868     * Returns whether this parameter is persistent. This is always true for C2Tuning and C2Setting,
869     * but may be false for C2Info. If true, this parameter persists across frames and applies to
870     * the current and subsequent frames. If false, this C2Info parameter only applies to the
871     * current frame and is not assumed to have the same value (or even be present) on subsequent
872     * frames, unless it is specified for those frames.
873     */
874    inline bool isPersistent() const { return _mIsPersistent; }
875
876    /// Returns the name of this param.
877    /// This defaults to the underlying C2Struct's name, but could be altered for a component.
878    inline C2String name() const { return _mName; }
879
880    /// Returns the parameter type
881    /// \todo fix this
882    inline C2Param::Type type() const { return _mType; }
883
884    template<typename T>
885    inline C2ParamDescriptor(bool isRequired, C2StringLiteral name, const T*)
886        : _mIsRequired(isRequired),
887          _mIsPersistent(true),
888          _mName(name),
889          _mType(T::typeIndex) { }
890
891    inline C2ParamDescriptor(
892            bool isRequired, C2StringLiteral name, C2Param::Type type)
893        : _mIsRequired(isRequired),
894          _mIsPersistent(true),
895          _mName(name),
896          _mType(type) { }
897
898private:
899    const bool _mIsRequired;
900    const bool _mIsPersistent;
901    const C2String _mName;
902    const C2Param::Type _mType;
903};
904
905/// \ingroup internal
906/// Define a structure without baseIndex.
907#define DEFINE_C2STRUCT_NO_BASE(name) \
908public: \
909    typedef C2##name##Struct _type; /**< type name shorthand */ \
910    const static std::initializer_list<const C2FieldDescriptor> fieldList; /**< structure fields */
911
912/// Define a structure with matching baseIndex.
913#define DEFINE_C2STRUCT(name) \
914public: \
915    enum : uint32_t { baseIndex = kParamIndex##name }; \
916    DEFINE_C2STRUCT_NO_BASE(name)
917
918/// Define a flexible structure with matching baseIndex.
919#define DEFINE_FLEX_C2STRUCT(name, flexMember) \
920public: \
921    FLEX(C2##name##Struct, flexMember) \
922    enum : uint32_t { baseIndex = kParamIndex##name | C2Param::BaseIndex::_kFlexibleFlag }; \
923    DEFINE_C2STRUCT_NO_BASE(name)
924
925/// \ingroup internal
926/// Describe a structure of a templated structure.
927#define DESCRIBE_TEMPLATED_C2STRUCT(strukt, list) \
928    template<> \
929    const std::initializer_list<const C2FieldDescriptor> strukt::fieldList = list;
930
931/// \deprecated
932/// Describe the fields of a structure using an initializer list.
933#define DESCRIBE_C2STRUCT(name, list) \
934    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = list;
935
936/**
937 * Describe a field of a structure.
938 * These must be in order.
939 *
940 * There are two ways to use this macro:
941 *
942 *  ~~~~~~~~~~~~~ (.cpp)
943 *  struct C2VideoWidthStruct {
944 *      int32_t mWidth;
945 *      C2VideoWidthStruct() {} // optional default constructor
946 *      C2VideoWidthStruct(int32_t _width) : mWidth(_width) {}
947 *
948 *      DEFINE_AND_DESCRIBE_C2STRUCT(VideoWidth)
949 *      C2FIELD(mWidth, "width")
950 *  };
951 *  ~~~~~~~~~~~~~
952 *
953 *  ~~~~~~~~~~~~~ (.cpp)
954 *  struct C2VideoWidthStruct {
955 *      int32_t mWidth;
956 *      C2VideoWidthStruct() = default; // optional default constructor
957 *      C2VideoWidthStruct(int32_t _width) : mWidth(_width) {}
958 *
959 *      DEFINE_C2STRUCT(VideoWidth)
960 *  } C2_PACK;
961 *
962 *  DESCRIBE_C2STRUCT(VideoWidth, {
963 *      C2FIELD(mWidth, "width")
964 *  })
965 *  ~~~~~~~~~~~~~
966 *
967 *  For flexible structures (those ending in T[]), use the flexible macros:
968 *
969 *  ~~~~~~~~~~~~~ (.cpp)
970 *  struct C2VideoFlexWidthsStruct {
971 *      int32_t mWidths[];
972 *      C2VideoFlexWidthsStruct(); // must have a default constructor
973 *
974 *  private:
975 *      // may have private constructors taking number of widths as the first argument
976 *      // This is used by the C2Param factory methods, e.g.
977 *      //   C2VideoFlexWidthsGlobalParam::alloc_unique(size_t, int32_t);
978 *      C2VideoFlexWidthsStruct(size_t flexCount, int32_t value) {
979 *          for (size_t i = 0; i < flexCount; ++i) {
980 *              mWidths[i] = value;
981 *          }
982 *      }
983 *
984 *      // If the last argument is T[N] or std::initializer_list<T>, the flexCount will
985 *      // be automatically calculated and passed by the C2Param factory methods, e.g.
986 *      //   int widths[] = { 1, 2, 3 };
987 *      //   C2VideoFlexWidthsGlobalParam::alloc_unique(widths);
988 *      template<unsigned N>
989 *      C2VideoFlexWidthsStruct(size_t flexCount, const int32_t(&init)[N]) {
990 *          for (size_t i = 0; i < flexCount; ++i) {
991 *              mWidths[i] = init[i];
992 *          }
993 *      }
994 *
995 *      DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(VideoFlexWidths, mWidths)
996 *      C2FIELD(mWidths, "widths")
997 *  };
998 *  ~~~~~~~~~~~~~
999 *
1000 *  ~~~~~~~~~~~~~ (.cpp)
1001 *  struct C2VideoFlexWidthsStruct {
1002 *      int32_t mWidths[];
1003 *      C2VideoFlexWidthsStruct(); // must have a default constructor
1004 *
1005 *      DEFINE_FLEX_C2STRUCT(VideoFlexWidths, mWidths)
1006 *  } C2_PACK;
1007 *
1008 *  DESCRIBE_C2STRUCT(VideoFlexWidths, {
1009 *      C2FIELD(mWidths, "widths")
1010 *  })
1011 *  ~~~~~~~~~~~~~
1012 *
1013 */
1014#define C2FIELD(member, name) \
1015  C2FieldDescriptor(&((_type*)(nullptr))->member, name),
1016
1017/// \deprecated
1018#define C2SOLE_FIELD(member, name) \
1019  C2FieldDescriptor(&_type::member, name, 0)
1020
1021/// Define a structure with matching baseIndex and start describing its fields.
1022/// This must be at the end of the structure definition.
1023#define DEFINE_AND_DESCRIBE_C2STRUCT(name) \
1024    DEFINE_C2STRUCT(name) }  C2_PACK; \
1025    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
1026
1027/// Define a flexible structure with matching baseIndex and start describing its fields.
1028/// This must be at the end of the structure definition.
1029#define DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember) \
1030    DEFINE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; \
1031    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
1032
1033/**
1034 * Parameter reflector class.
1035 *
1036 * This class centralizes the description of parameter structures. This can be shared
1037 * by multiple components as describing a parameter does not imply support of that
1038 * parameter. However, each supported parameter and any dependent structures within
1039 * must be described by the parameter reflector provided by a component.
1040 */
1041class C2ParamReflector {
1042public:
1043    /**
1044     *  Describes a parameter structure.
1045     *
1046     *  \param[in] paramIndex the base index of the parameter structure
1047     *
1048     *  \return the description of the parameter structure
1049     *  \retval nullptr if the parameter is not supported by this reflector
1050     *
1051     *  This methods shall not block and return immediately.
1052     *
1053     *  \note this class does not take a set of indices because we would then prefer
1054     *  to also return any dependent structures, and we don't want this logic to be
1055     *  repeated in each reflector. Alternately, this could just return a map of all
1056     *  descriptions, but we want to conserve memory if client only wants the description
1057     *  of a few indices.
1058     */
1059    virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) = 0;
1060
1061protected:
1062    virtual ~C2ParamReflector() = default;
1063};
1064
1065/**
1066 * A useable supported values for a field.
1067 *
1068 * This can be either a range or a set of values. The range can be linear or geometric with a
1069 * clear minimum and maximum value, and can have an optional step size or geometric ratio. Values
1070 * can optionally represent flags.
1071 *
1072 * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
1073 */
1074template<typename T>
1075struct C2TypedFieldSupportedValues {
1076//public:
1077    enum Type {
1078        RANGE,      ///< a numeric range that can be continuous or discrete
1079        VALUES,     ///< a list of values
1080        FLAGS       ///< a list of flags that can be OR-ed
1081    };
1082
1083    Type type;
1084
1085    struct {
1086        T min;
1087        T max;
1088        T step;
1089        T nom;
1090        T denom;
1091    } range;
1092    std::vector<T> values;
1093
1094    C2TypedFieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
1095        : type(RANGE),
1096          range{min, max, step, (T)1, (T)1} { }
1097
1098    C2TypedFieldSupportedValues(T min, T max, T nom, T den) :
1099        type(RANGE),
1100        range{min, max, (T)0, nom, den} { }
1101
1102    C2TypedFieldSupportedValues(bool flags, std::initializer_list<T> list) :
1103        type(flags ? FLAGS : VALUES),
1104        values(list) {}
1105};
1106
1107/**
1108 * Generic supported values for a field.
1109 *
1110 * This can be either a range or a set of values. The range can be linear or geometric with a
1111 * clear minimum and maximum value, and can have an optional step size or geometric ratio. Values
1112 * can optionally represent flags.
1113 *
1114 * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
1115 */
1116struct C2FieldSupportedValues {
1117//public:
1118    enum Type {
1119        RANGE,      ///< a numeric range that can be continuous or discrete
1120        VALUES,     ///< a list of values
1121        FLAGS       ///< a list of flags that can be OR-ed
1122    };
1123
1124    Type type;
1125
1126    typedef C2Value::Primitive Primitive;
1127
1128    struct {
1129        Primitive min;
1130        Primitive max;
1131        Primitive step;
1132        Primitive nom;
1133        Primitive denom;
1134    } range;
1135    std::vector<Primitive> values;
1136
1137    template<typename T>
1138    C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
1139        : type(RANGE),
1140          range{min, max, step, (T)1, (T)1} { }
1141
1142    template<typename T>
1143    C2FieldSupportedValues(T min, T max, T nom, T den) :
1144        type(RANGE),
1145        range{min, max, (T)0, nom, den} { }
1146
1147    template<typename T>
1148    C2FieldSupportedValues(bool flags, std::initializer_list<T> list)
1149        : type(flags ? FLAGS : VALUES),
1150          range{(T)0, (T)0, (T)0, (T)0, (T)0} {
1151        for(T value : list) {
1152            values.emplace_back(value);
1153        }
1154    }
1155
1156    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
1157    C2FieldSupportedValues(bool flags, const T*)
1158        : type(flags ? FLAGS : VALUES),
1159          range{(T)0, (T)0, (T)0, (T)0, (T)0} {
1160              C2FieldDescriptor::named_values_type named = C2FieldDescriptor::namedValuesFor(*(T*)0);
1161        for (const C2FieldDescriptor::named_value_type &item : named) {
1162            values.emplace_back(item.second);
1163        }
1164    }
1165};
1166
1167/// @}
1168
1169}  // namespace android
1170
1171#endif  // C2PARAM_H_
1172