• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 namespace 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
89 struct _C2ParamManipulator;
90 
91 /**
92  * Parameter base class.
93  */
94 struct 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     //
111 public:
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
BaseIndexC2Param::BaseIndex162         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
isVendorC2Param::BaseIndex168         inline bool isVendor() const { return mIndex & kVendorFlag; }
169 
170         /// returns true iff this is a flexible parameter (with variable size)
isFlexibleC2Param::BaseIndex171         inline bool isFlexible() const { return mIndex & kFlexibleFlag; }
172 
173         /// returns the base type: the index for the underlying struct
baseIndexC2Param::BaseIndex174         inline unsigned int baseIndex() const { return mIndex & kBaseMask; }
175 
176         /// returns the param index for the underlying struct
paramIndexC2Param::BaseIndex177         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)
isGlobalC2Param::Type191         inline bool isGlobal() const { return (mIndex & kDirMask) == kDirGlobal; }
192         /// returns true iff this is an input or input stream parameter
forInputC2Param::Type193         inline bool forInput() const { return (mIndex & kDirMask) == kDirInput; }
194         /// returns true iff this is an output or output stream parameter
forOutputC2Param::Type195         inline bool forOutput() const { return (mIndex & kDirMask) == kDirOutput; }
196 
197         /// returns true iff this is a stream parameter
forStreamC2Param::Type198         inline bool forStream() const { return mIndex & kStreamFlag; }
199         /// returns true iff this is a port (input or output) parameter
forPortC2Param::Type200         inline bool forPort() const   { return !forStream() && !isGlobal(); }
201 
202         /// returns the parameter type: the parameter index without the stream ID
typeC2Param::Type203         inline uint32_t type() const { return mIndex & (~kStreamIdMask); }
204 
205         /// return the kind of this param
kindC2Param::Type206         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
TypeC2Param::Type217         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          */
setPortC2Param::Type237         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
uint32_tC2Param::Index252         inline operator uint32_t() const { return mIndex; }
253 
254         /// constructor/conversion from uint32_t
IndexC2Param::Index255         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
streamC2Param::Index261         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          */
isValidC2Param::Index273         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
rawStreamC2Param::Index281         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.
makeStreamIdC2Param::Index287         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          */
setStreamC2Param::Index299         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 
308 public:
309     // public getters for Index methods
310 
311     /// returns true iff this is a vendor extension parameter
isVendorC2Param312     inline bool isVendor() const { return _mIndex.isVendor(); }
313     /// returns true iff this is a flexible parameter
isFlexibleC2Param314     inline bool isFlexible() const { return _mIndex.isFlexible(); }
315     /// returns true iff this is a global parameter (not for input nor output)
isGlobalC2Param316     inline bool isGlobal() const { return _mIndex.isGlobal(); }
317     /// returns true iff this is an input or input stream parameter
forInputC2Param318     inline bool forInput() const { return _mIndex.forInput(); }
319     /// returns true iff this is an output or output stream parameter
forOutputC2Param320     inline bool forOutput() const { return _mIndex.forOutput(); }
321 
322     /// returns true iff this is a stream parameter
forStreamC2Param323     inline bool forStream() const { return _mIndex.forStream(); }
324     /// returns true iff this is a port (input or output) parameter
forPortC2Param325     inline bool forPort() const   { return _mIndex.forPort(); }
326 
327     /// returns the stream ID or ~0 if not a stream
streamC2Param328     inline unsigned stream() const { return _mIndex.stream(); }
329 
330     /// returns the parameter type: the parameter index without the stream ID
typeC2Param331     inline uint32_t type() const { return _mIndex.type(); }
332 
333     /// returns the kind of this parameter
kindC2Param334     inline Kind kind() const { return _mIndex.kind(); }
335 
336     /// returns the size of the parameter or 0 if the parameter is invalid
sizeC2Param337     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
FromC2Param352     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 
372 protected:
373     /// sets the stream field. Returns true iff successful.
setStreamC2Param374     inline bool setStream(unsigned stream) {
375         return _mIndex.setStream(stream);
376     }
377 
378     /// sets the port (direction). Returns true iff successful.
setPortC2Param379     inline bool setPort(bool output) {
380         return _mIndex.setPort(output);
381     }
382 
383 public:
384     /// invalidate this parameter. There is no recovery from this call; e.g. parameter
385     /// cannot be 'corrected' to be valid.
invalidateC2Param386     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.
updateFromC2Param390     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 
398 protected:
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
C2ParamC2Param418     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
C2ParamC2Param427     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 
438 private:
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)
_baseIndexC2Param443     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.
equalsC2Param447     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  */
465 struct C2Setting : public C2Param {
466 protected:
467     template<typename ...Args>
C2SettingC2Setting468     inline C2Setting(const Args(&... args)) : C2Param(args...) { }
469 public: // TODO
470     enum : uint32_t { indexFlags = Type::kTypeSetting };
471 };
472 
473 /**
474  * Tuning base structure for component method signatures. Wrap constructors.
475  */
476 struct C2Tuning : public C2Setting {
477 protected:
478     template<typename ...Args>
C2TuningC2Tuning479     inline C2Tuning(const Args(&... args)) : C2Setting(args...) { }
480 public: // TODO
481     enum : uint32_t { indexFlags = Type::kTypeTuning };
482 };
483 
484 /**
485  * Info base structure for component method signatures. Wrap constructors.
486  */
487 struct C2Info : public C2Param {
488 protected:
489     template<typename ...Args>
C2InfoC2Info490     inline C2Info(const Args(&... args)) : C2Param(args...) { }
491 public: // 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  */
503 struct _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>
_C2FieldId_C2FieldId511     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      */
_C2FieldId_C2FieldId522     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>
_C2FieldId_C2FieldId533     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>
_C2FieldId_C2FieldId544     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 
569 private:
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  */
577 struct C2ParamField {
578 //public:
579     // TODO: fix what this is for T[] (for now size becomes T[1])
580     template<typename S, typename T>
C2ParamFieldC2ParamField581     inline C2ParamField(S* param, T* offset)
582         : _mIndex(param->index()),
583           _mFieldId(offset) {}
584 
585     template<typename R, typename T, typename U>
C2ParamFieldC2ParamField586     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 
599 private:
600     C2Param::Index _mIndex;
601     _C2FieldId _mFieldId;
602 };
603 
604 /**
605  * A shared (union) representation of numeric values
606  */
607 class C2Value {
608 public:
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
Primitive(int32_t value)618         Primitive(int32_t value)  : i32(value) { }
Primitive(uint32_t value)619         Primitive(uint32_t value) : u32(value) { }
Primitive(int64_t value)620         Primitive(int64_t value)  : i64(value) { }
Primitive(uint64_t value)621         Primitive(uint64_t value) : u64(value) { }
Primitive(float value)622         Primitive(float value)    : fp(value)  { }
623 
Primitive()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>
C2Value(T value)644     C2Value(T value)  : mType(typeFor<T>()),  mValue(value) { }
645 
C2Value()646     C2Value() : mType(NO_INIT) { }
647 
type()648     inline Type type() const { return mType; }
649 
650     template<typename T>
get(T * value)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 
659 private:
660     Type mType;
661     Primitive mValue;
662 };
663 
664 template<> const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
665 template<> const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; }
666 template<> const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; }
667 template<> const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; }
668 template<> const float &C2Value::Primitive::ref<float>() const { return fp; }
669 
670 template<> constexpr C2Value::Type C2Value::typeFor<int32_t>() { return INT32; }
671 template<> constexpr C2Value::Type C2Value::typeFor<int64_t>() { return INT64; }
672 template<> constexpr C2Value::Type C2Value::typeFor<uint32_t>() { return UINT32; }
673 template<> constexpr C2Value::Type C2Value::typeFor<uint64_t>() { return UINT64; }
674 template<> 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  */
683 struct 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 
C2FieldDescriptorC2FieldDescriptor720     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>
C2FieldDescriptorC2FieldDescriptor724     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>
C2FieldDescriptorC2FieldDescriptor742     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
typeC2FieldDescriptor749     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.
lengthC2FieldDescriptor752     inline size_t length() const { return _mLength; }
753     /// returns the name of the field
nameC2FieldDescriptor754     inline C2StringLiteral name() const { return _mName; }
755 
namedValuesC2FieldDescriptor756     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 
764 private:
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
getTypeC2FieldDescriptor779     inline static Type getType(int32_t*)  { return INT32; }
getTypeC2FieldDescriptor780     inline static Type getType(uint32_t*) { return UINT32; }
getTypeC2FieldDescriptor781     inline static Type getType(int64_t*)  { return INT64; }
getTypeC2FieldDescriptor782     inline static Type getType(uint64_t*) { return UINT64; }
getTypeC2FieldDescriptor783     inline static Type getType(float*)    { return FLOAT; }
getTypeC2FieldDescriptor784     inline static Type getType(char*)     { return STRING; }
getTypeC2FieldDescriptor785     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>
getTypeC2FieldDescriptor789     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)>
getTypeC2FieldDescriptor797     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) \
804 template<> 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.
810 DEFINE_NO_NAMED_VALUES_FOR(int32_t)
811 DEFINE_NO_NAMED_VALUES_FOR(uint32_t)
812 DEFINE_NO_NAMED_VALUES_FOR(int64_t)
813 DEFINE_NO_NAMED_VALUES_FOR(uint64_t)
814 DEFINE_NO_NAMED_VALUES_FOR(uint8_t)
815 DEFINE_NO_NAMED_VALUES_FOR(char)
816 DEFINE_NO_NAMED_VALUES_FOR(float)
817 
818 /**
819  * Describes the fields of a structure.
820  */
821 struct C2StructDescriptor {
822 public:
823     /// Returns the parameter type
baseIndexC2StructDescriptor824     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.
numFieldsC2StructDescriptor828     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;
cbeginC2StructDescriptor832     inline field_iterator cbegin() const { return _mFields.cbegin(); }
cendC2StructDescriptor833     inline field_iterator cend() const { return _mFields.cend(); }
834 
835     // only supplying const iterator - but these are needed for range based loops
beginC2StructDescriptor836     inline field_iterator begin() const { return _mFields.cbegin(); }
endC2StructDescriptor837     inline field_iterator end() const { return _mFields.cend(); }
838 
839     template<typename T>
C2StructDescriptorC2StructDescriptor840     inline C2StructDescriptor(T*)
841         : C2StructDescriptor(T::baseIndex, T::fieldList) { }
842 
C2StructDescriptorC2StructDescriptor843     inline C2StructDescriptor(
844             C2Param::BaseIndex type,
845             std::initializer_list<const C2FieldDescriptor> fields)
846         : _mType(type), _mFields(fields) { }
847 
848 private:
849     const C2Param::BaseIndex _mType;
850     const std::vector<const C2FieldDescriptor> _mFields;
851 };
852 
853 /**
854  * Describes parameters for a component.
855  */
856 struct C2ParamDescriptor {
857 public:
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      */
isRequiredC2ParamDescriptor865     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      */
isPersistentC2ParamDescriptor874     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.
nameC2ParamDescriptor878     inline C2String name() const { return _mName; }
879 
880     /// Returns the parameter type
881     /// \todo fix this
typeC2ParamDescriptor882     inline C2Param::Type type() const { return _mType; }
883 
884     template<typename T>
C2ParamDescriptorC2ParamDescriptor885     inline C2ParamDescriptor(bool isRequired, C2StringLiteral name, const T*)
886         : _mIsRequired(isRequired),
887           _mIsPersistent(true),
888           _mName(name),
889           _mType(T::typeIndex) { }
890 
C2ParamDescriptorC2ParamDescriptor891     inline C2ParamDescriptor(
892             bool isRequired, C2StringLiteral name, C2Param::Type type)
893         : _mIsRequired(isRequired),
894           _mIsPersistent(true),
895           _mName(name),
896           _mType(type) { }
897 
898 private:
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) \
908 public: \
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) \
914 public: \
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) \
920 public: \
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  */
1041 class C2ParamReflector {
1042 public:
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 
1061 protected:
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  */
1074 template<typename T>
1075 struct 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))
typeC2TypedFieldSupportedValues1095         : type(RANGE),
1096           range{min, max, step, (T)1, (T)1} { }
1097 
C2TypedFieldSupportedValuesC2TypedFieldSupportedValues1098     C2TypedFieldSupportedValues(T min, T max, T nom, T den) :
1099         type(RANGE),
1100         range{min, max, (T)0, nom, den} { }
1101 
C2TypedFieldSupportedValuesC2TypedFieldSupportedValues1102     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  */
1116 struct 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))
typeC2FieldSupportedValues1139         : type(RANGE),
1140           range{min, max, step, (T)1, (T)1} { }
1141 
1142     template<typename T>
C2FieldSupportedValuesC2FieldSupportedValues1143     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>
C2FieldSupportedValuesC2FieldSupportedValues1148     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))>
C2FieldSupportedValuesC2FieldSupportedValues1157     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