/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef REFLECTED_PARAM_BUILDER_H_
#define REFLECTED_PARAM_BUILDER_H_
#include <map>
#include <memory>
#include <C2.h>
#include <C2Param.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AData.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AString.h>
namespace android {
/**
* Utility class to query and update Codec 2.0 configuration values. Use custom dictionary as
* AMessage cannot represent all types of Codec 2.0 parameters and C2Value cannot represent
* all types of SDK values. We want to be precise when setting standard parameters (use C2Value
* for arithmetic values), but also support int32 and int64 for SDK values specifically for
* vendor parameters (as SDK API does not allow specifying proper type.) When querying fields,
* we can use C2Values as they are defined.
*
* Item => Codec 2.0 value mappings:
* CValue::type => type
* int32 => int32, ctr32 or uint32
* int64 => int64, ctr64 or uint64
* AString => string
* ABuffer => blob
* 'Rect' => C2RectStruct (not exposed in SDK as a rectangle)
*/
class ReflectedParamUpdater {
public:
ReflectedParamUpdater() = default;
~ReflectedParamUpdater() = default;
/**
* Element for values
*/
struct Value : public AData<C2Value, int32_t, int64_t, AString, sp<ABuffer>>::Basic {
// allow construction from base types
Value() = default;
explicit Value(C2Value i) { set(i); }
explicit Value(int32_t i) { set(i); }
explicit Value(int64_t i) { set(i); }
explicit Value(const AString &i) { set(i); }
explicit Value(const sp<ABuffer> &i) { set(i); }
};
struct Dict : public std::map<std::string, Value> {
Dict() = default;
std::string debugString(size_t indent = 0) const;
};
/**
* Enumerates all fields of the parameter descriptors supplied, so that this opbject can later
* query and update these.
*
* For now only first-level fields are supported. Also, array fields are not supported.
*
* \param reflector C2ParamReflector object for C2Param reflection.
* \param paramDescs vector of C2ParamDescriptor objects that this object
* would recognize when building params.
*/
void addParamDesc(
const std::shared_ptr<C2ParamReflector> &reflector,
const std::vector<std::shared_ptr<C2ParamDescriptor>> ¶mDescs);
/**
* Adds fields of a standard parameter (that may not be supported by the parameter reflector
* or may not be listed as a supported value by the component). If the parameter name is
* used for another parameter, this operation is a no-op. (Technically, this is by fields).
*
* \param T standard parameter type
* \param name parameter name
*/
template<typename T>
void addStandardParam(const std::string &name, C2ParamDescriptor::attrib_t attrib =
C2ParamDescriptor::IS_READ_ONLY) {
addParamDesc(std::make_shared<C2ParamDescriptor>(
C2Param::Index(T::PARAM_TYPE), attrib, name.c_str()),
C2StructDescriptor((T*)nullptr), nullptr /* descriptor */);
}
/**
* Adds fields of a structure (or a parameater) described by the struct descriptor. If
* reflector is provided, fields of sub-structures are also added. Otherwise, only top-level
* fundamental typed fields (arithmetic, string and blob) are added.
*
* \param paramDesc parameter descriptor
* \param fieldDesc field descriptor
* \param path path/name of the structure (field or parent parameter)
* \param offset offset of the structure in the parameter
* \param reflector C2ParamReflector object for C2Param reflection (may be null)
*/
void addParamStructDesc(
std::shared_ptr<C2ParamDescriptor> paramDesc, C2String path, size_t offset,
const C2StructDescriptor &structDesc,
const std::shared_ptr<C2ParamReflector> &reflector);
/**
* Adds fields of a parameter described by the struct descriptor. If reflector is provided,
* fields of sub-structures are also added. Otherwise, only top-level fundamental typed fields
* (arithmetic, string and blob) are added.
*
* \param paramDesc parameter descriptor
* \param fieldDesc field descriptor
* \param reflector C2ParamReflector object for C2Param reflection (may be null)
* \param markVendor TEMP if true, prefix vendor parameter names with "vendor."
*/
void addParamDesc(
std::shared_ptr<C2ParamDescriptor> paramDesc, const C2StructDescriptor &structDesc,
const std::shared_ptr<C2ParamReflector> &reflector,
bool markVendor = true);
/**
* Returns the name of the parameter for an index.
*/
std::string getParamName(C2Param::Index index) const;
/**
* Get list of param indices from field names and values in AMessage object.
*
* TODO: This should be in the order that they are listed by the component.
*
* \param params[in] Dict object with field name to value pairs.
* \param vec[out] vector to store the indices from |params|.
*/
void getParamIndicesFromMessage(
const Dict ¶ms,
std::vector<C2Param::Index> *vec /* nonnull */) const;
/**
* Get list of param indices from field names (only) in AMessage object.
*
* \param params[in] Vector object with field names.
* \param vec[out] vector to store the indices from |params|.
*/
void getParamIndicesForKeys(
const std::vector<std::string> &keys,
std::vector<C2Param::Index> *vec /* nonnull */) const;
/**
* Update C2Param objects from field name and value in AMessage object.
*
* \param params[in] Dict object with field name to value pairs.
* \param vec[in,out] vector of the C2Param objects to be updated.
*/
void updateParamsFromMessage(
const Dict ¶ms,
std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const;
/**
* Get fields from C2Param objects in AMessage object.
*
* \param params[in] vector of the C2Param objects to be queried
* \return a Dict object containing the known parameters
*/
Dict getParams(
const std::vector<C2Param*> ¶ms /* nonnull */) const;
Dict getParams(
const std::vector<std::unique_ptr<C2Param>> ¶ms /* nonnull */) const;
/**
* Clear param descriptors in this object.
*/
void clear();
private:
struct FieldDesc {
std::shared_ptr<C2ParamDescriptor> paramDesc;
std::unique_ptr<C2FieldDescriptor> fieldDesc;
size_t offset;
};
std::map<std::string, FieldDesc> mMap;
std::map<C2Param::Index, std::string> mParamNames;
void parseMessageAndDoWork(
const Dict ¶ms,
std::function<void(const std::string &, const FieldDesc &, const void *, size_t)> work) const;
C2_DO_NOT_COPY(ReflectedParamUpdater);
};
} // namespace android
#endif // REFLECTED_PARAM_BUILDER_H_