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