Home | History | Annotate | Download | only in sfplugin
      1 /*
      2  * Copyright (C) 2018 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 C_CODEC_CONFIG_H_
     18 #define C_CODEC_CONFIG_H_
     19 
     20 #include <map>
     21 #include <memory>
     22 #include <set>
     23 #include <vector>
     24 
     25 #include <C2Component.h>
     26 #include <codec2/hidl/client.h>
     27 
     28 #include <utils/RefBase.h>
     29 
     30 #include "InputSurfaceWrapper.h"
     31 #include "ReflectedParamUpdater.h"
     32 
     33 namespace android {
     34 
     35 struct AMessage;
     36 struct StandardParams;
     37 
     38 /**
     39  * Struct managing the codec configuration for CCodec.
     40  */
     41 struct CCodecConfig {
     42 
     43     /**
     44      * Domain consists of a bitmask divided into fields, and specifiers work by excluding other
     45      * values in those domains.
     46      *
     47      * Component domains are composed by or-ing the individual IS_ constants, e.g.
     48      * IS_DECODER | IS_AUDIO.
     49      *
     50      * Config specifiers are composed by or-ing the individual mask constants, and
     51      * and-ing these groups: e.g. (DECODER | ENCODER) & AUDIO.
     52      *
     53      * The naming of these constants was to limit the length of mask names as these are used more
     54      * commonly as masks.
     55      */
     56     enum Domain : uint32_t {
     57         GUARD_BIT   = (1 << 1),   ///< this is to prevent against accidental && or || usage
     58         IS_AUDIO    = (1 << 2),   ///< for audio codecs
     59         IS_VIDEO    = (1 << 3),   ///< for video codecs
     60         IS_IMAGE    = (1 << 4),   ///< for image codecs
     61         OTHER_DOMAIN = (1 << 5),  ///< for other domains
     62 
     63         IS_ENCODER  = (1 << 6),   ///< for encoders
     64         IS_DECODER  = (1 << 7),   ///< for decoders
     65         OTHER_KIND  = (1 << 8),   ///< for other domains
     66 
     67         IS_PARAM    = (1 << 9),   ///< for setParameter
     68         IS_CONFIG   = (1 << 10),  ///< for configure
     69         IS_READ     = (1 << 11),  ///< for getFormat
     70 
     71         IS_INPUT    = (1 << 12),  ///< for input port (getFormat)
     72         IS_OUTPUT   = (1 << 13),  ///< for output port (getFormat)
     73         IS_RAW      = (1 << 14),  ///< for raw port (input-encoder, output-decoder)
     74         IS_CODED    = (1 << 15),  ///< for coded port (input-decoder, output-encoder)
     75 
     76         ALL     = ~0U,
     77         NONE    = 0,
     78 
     79         AUDIO   = ~(IS_IMAGE | IS_VIDEO | OTHER_DOMAIN),
     80         VIDEO   = ~(IS_AUDIO | IS_IMAGE | OTHER_DOMAIN),
     81         IMAGE   = ~(IS_AUDIO | IS_VIDEO | OTHER_DOMAIN),
     82 
     83         DECODER = ~(IS_ENCODER | OTHER_KIND),
     84         ENCODER = ~(IS_DECODER | OTHER_KIND),
     85 
     86         PARAM   = ~(IS_CONFIG | IS_READ),
     87         CONFIG  = ~(IS_PARAM  | IS_READ),
     88         READ    = ~(IS_CONFIG | IS_PARAM),
     89 
     90         INPUT   = ~(IS_OUTPUT | IS_RAW    | IS_CODED),
     91         OUTPUT  = ~(IS_INPUT  | IS_RAW    | IS_CODED),
     92         RAW     = ~(IS_INPUT  | IS_OUTPUT | IS_CODED),
     93         CODED   = ~(IS_INPUT  | IS_RAW    | IS_OUTPUT),
     94     };
     95 
     96     // things required to manage formats
     97     std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs;
     98     std::shared_ptr<C2ParamReflector> mReflector;
     99 
    100     std::shared_ptr<ReflectedParamUpdater> mParamUpdater;
    101 
    102     Domain mDomain; // component domain
    103     Domain mInputDomain; // input port domain
    104     Domain mOutputDomain; // output port domain
    105 
    106     // standard MediaCodec to Codec 2.0 params mapping
    107     std::shared_ptr<StandardParams> mStandardParams;
    108 
    109     std::set<C2Param::Index> mSupportedIndices; ///< indices supported by the component
    110     std::set<C2Param::Index> mSubscribedIndices; ///< indices to subscribe to
    111     size_t mSubscribedIndicesSize; ///< count of currently subscribed indices
    112 
    113     sp<AMessage> mInputFormat;
    114     sp<AMessage> mOutputFormat;
    115 
    116     std::shared_ptr<InputSurfaceWrapper> mInputSurface;
    117     std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
    118 
    119     /// the current configuration. Updated after configure() and based on configUpdate in
    120     /// onWorkDone
    121     std::map<C2Param::Index, std::unique_ptr<C2Param>> mCurrentConfig;
    122 
    123     typedef std::function<c2_status_t(std::unique_ptr<C2Param>&)> LocalParamValidator;
    124 
    125     /// Parameter indices tracked in current config that are not supported by the component.
    126     /// these are provided so that optional parameters can remain in the current configuration.
    127     /// as such, these parameters have no dependencies. TODO: use C2InterfaceHelper for this.
    128     /// For now support a validation function.
    129     std::map<C2Param::Index, LocalParamValidator> mLocalParams;
    130 
    131     CCodecConfig();
    132 
    133     /// initializes the members required to manage the format: descriptors, reflector,
    134     /// reflected param helper, domain, standard params, and subscribes to standard
    135     /// indices.
    136     status_t initialize(
    137             const std::shared_ptr<Codec2Client> &client,
    138             const std::shared_ptr<Codec2Client::Component> &component);
    139 
    140 
    141     /**
    142      * Adds a locally maintained parameter. This is used for output configuration that can be
    143      * appended to the output buffers in case it is not supported by the component.
    144      */
    145     template<typename T>
    146     bool addLocalParam(
    147             const std::string &name,
    148             C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
    149             std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
    150                 std::function<c2_status_t(std::unique_ptr<T>&)>()) {
    151         C2Param::Index index = T::PARAM_TYPE;
    152         if (mSupportedIndices.count(index) || mLocalParams.count(index)) {
    153             if (mSupportedIndices.count(index)) {
    154                 mSubscribedIndices.emplace(index);
    155             }
    156             ALOGD("ignoring local param %s (%#x) as it is already %s",
    157                     name.c_str(), (uint32_t)index, mSupportedIndices.count(index) ? "supported" : "local");
    158             return false; // already supported by the component or already added
    159         }
    160 
    161         // wrap typed validator into untyped validator
    162         LocalParamValidator validator;
    163         if (validator_) {
    164             validator = [validator_](std::unique_ptr<C2Param>& p){
    165                 c2_status_t res = C2_BAD_VALUE;
    166                 std::unique_ptr<T> typed(static_cast<T*>(p.release()));
    167                 // if parameter is correctly typed
    168                 if (T::From(typed.get())) {
    169                     res = validator_(typed);
    170                     p.reset(typed.release());
    171                 }
    172                 return res;
    173             };
    174         }
    175 
    176         mLocalParams.emplace(index, validator);
    177         mParamUpdater->addStandardParam<T>(name, attrib);
    178         return true;
    179     }
    180 
    181     /**
    182      * Adds a locally maintained parameter with a default value.
    183      */
    184     template<typename T>
    185     bool addLocalParam(
    186             std::unique_ptr<T> default_,
    187             const std::string &name,
    188             C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
    189             std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
    190                 std::function<c2_status_t(std::unique_ptr<T>&)>()) {
    191         if (addLocalParam<T>(name, attrib, validator_)) {
    192             if (validator_) {
    193                 c2_status_t err = validator_(default_);
    194                 if (err != C2_OK) {
    195                     ALOGD("default value for %s is invalid => %s", name.c_str(), asString(err));
    196                     return false;
    197                 }
    198             }
    199             mCurrentConfig[T::PARAM_TYPE] = std::move(default_);
    200             return true;
    201         }
    202         return false;
    203     }
    204 
    205     template<typename T>
    206     bool addLocalParam(
    207             T *default_, const std::string &name,
    208             C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
    209             std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
    210                 std::function<c2_status_t(std::unique_ptr<T>&)>()) {
    211         return addLocalParam(std::unique_ptr<T>(default_), name, attrib, validator_);
    212     }
    213 
    214     /// Applies configuration updates, and updates format in the specific domain.
    215     /// Returns true if formats were updated
    216     /// \param domain input/output bitmask
    217     bool updateConfiguration(
    218             std::vector<std::unique_ptr<C2Param>> &configUpdate, Domain domain);
    219 
    220     /**
    221      * Applies SDK configurations in a specific configuration domain.
    222      * Updates relevant input/output formats and subscribes to parameters specified in the
    223      * configuration.
    224      * \param domain config/setParam bitmask
    225      * \param blocking blocking mode to use with the component
    226      */
    227     status_t getConfigUpdateFromSdkParams(
    228             std::shared_ptr<Codec2Client::Component> component,
    229             const sp<AMessage> &sdkParams, Domain domain,
    230             c2_blocking_t blocking,
    231             std::vector<std::unique_ptr<C2Param>> *configUpdate) const;
    232 
    233     /**
    234      * Applies a configuration update to the component.
    235      * Updates relevant input/output formats and subscribes to parameters specified in the
    236      * configuration.
    237      * \param blocking blocking mode to use with the component
    238      */
    239     status_t setParameters(
    240             std::shared_ptr<Codec2Client::Component> component,
    241             std::vector<std::unique_ptr<C2Param>> &configUpdate,
    242             c2_blocking_t blocking);
    243 
    244     /// Queries subscribed indices (which contains all SDK-exposed values) and updates
    245     /// input/output formats.
    246     status_t queryConfiguration(
    247             const std::shared_ptr<Codec2Client::Component> &component);
    248 
    249     /// Queries a configuration parameter value. Returns nullptr if the parameter is not
    250     /// part of the current configuration
    251     const C2Param *getConfigParameterValue(C2Param::Index index) const;
    252 
    253     /**
    254      * Object that can be used to access configuration parameters and if they change.
    255      */
    256     template<typename T>
    257     struct Watcher {
    258         ~Watcher() = default;
    259 
    260         /// returns true if the value of this configuration has changed
    261         bool hasChanged() const {
    262             const C2Param *value = mParent->getConfigParameterValue(mIndex);
    263             if (value && mValue) {
    264                 return *value != *mValue;
    265             } else {
    266                 return value != mValue.get();
    267             }
    268         }
    269 
    270         /// updates the current value and returns it
    271         std::shared_ptr<const T> update() {
    272             const C2Param *value = mParent->getConfigParameterValue(mIndex);
    273             if (value) {
    274                 mValue = std::shared_ptr<const T>(T::From(C2Param::Copy(*value).release()));
    275             }
    276             return mValue;
    277         }
    278 
    279     private:
    280         Watcher(C2Param::Index index, const CCodecConfig *parent)
    281             : mParent(parent), mIndex(index) {
    282             update();
    283         }
    284 
    285         friend struct CCodecConfig;
    286 
    287         const CCodecConfig *mParent;
    288         std::shared_ptr<const T> mValue;
    289         C2Param::Index mIndex;
    290     };
    291 
    292     /**
    293      * Returns a watcher object for a parameter.
    294      */
    295     template<typename T>
    296     Watcher<T> watch(C2Param::Index index = T::PARAM_TYPE) const {
    297         if (index.type() != T::PARAM_TYPE) {
    298             __builtin_trap();
    299         }
    300         return Watcher<T>(index, this);
    301     }
    302 
    303 private:
    304 
    305     /// initializes the standard MediaCodec to Codec 2.0 params mapping
    306     void initializeStandardParams();
    307 
    308     /// Adds indices to the subscribed indices, and updated subscription to component
    309     /// \param blocking blocking mode to use with the component
    310     status_t subscribeToConfigUpdate(
    311             const std::shared_ptr<Codec2Client::Component> &component,
    312             const std::vector<C2Param::Index> &indices,
    313             c2_blocking_t blocking = C2_DONT_BLOCK);
    314 
    315     /// Updates formats in the specific domain. Returns true if any of the formats have changed.
    316     /// \param domain input/output bitmask
    317     bool updateFormats(Domain domain);
    318 
    319     /// Gets SDK format from codec 2.0 reflected configuration
    320     /// \param domain input/output bitmask
    321     sp<AMessage> getSdkFormatForDomain(
    322             const ReflectedParamUpdater::Dict &reflected, Domain domain) const;
    323 
    324     /**
    325      * Converts a set of configuration parameters in an AMessage to a list of path-based Codec
    326      * 2.0 configuration parameters.
    327      *
    328      * \param domain config/setParam bitmask
    329      */
    330     ReflectedParamUpdater::Dict getReflectedFormat(
    331             const sp<AMessage> &config, Domain domain) const;
    332 };
    333 
    334 DEFINE_ENUM_OPERATORS(CCodecConfig::Domain)
    335 
    336 }  // namespace android
    337 
    338 #endif  // C_CODEC_H_
    339 
    340