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