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 REFLECTED_PARAM_BUILDER_H_
18 #define REFLECTED_PARAM_BUILDER_H_
19 
20 #include <map>
21 #include <memory>
22 
23 #include <C2.h>
24 #include <C2Param.h>
25 
26 #include <media/stagefright/foundation/ABuffer.h>
27 #include <media/stagefright/foundation/AData.h>
28 #include <media/stagefright/foundation/AMessage.h>
29 #include <media/stagefright/foundation/AString.h>
30 
31 namespace android {
32 
33 /**
34  * Utility class to query and update Codec 2.0 configuration values. Use custom dictionary as
35  * AMessage cannot represent all types of Codec 2.0 parameters and C2Value cannot represent
36  * all types of SDK values. We want to be precise when setting standard parameters (use C2Value
37  * for arithmetic values), but also support int32 and int64 for SDK values specifically for
38  * vendor parameters (as SDK API does not allow specifying proper type.) When querying fields,
39  * we can use C2Values as they are defined.
40  *
41  *      Item => Codec 2.0 value mappings:
42  *     CValue::type => type
43  *     int32 => int32, ctr32 or uint32
44  *     int64 => int64, ctr64 or uint64
45  *     AString => string
46  *     ABuffer => blob
47  *     'Rect' => C2RectStruct (not exposed in SDK as a rectangle)
48  */
49 class ReflectedParamUpdater {
50 public:
51     ReflectedParamUpdater() = default;
52     ~ReflectedParamUpdater() = default;
53 
54     /**
55      * Element for values
56      */
57     struct Value : public AData<C2Value, int32_t, int64_t, AString, sp<ABuffer>>::Basic {
58         // allow construction from base types
59         Value() = default;
ValueValue60         explicit Value(C2Value i)            { set(i); }
ValueValue61         explicit Value(int32_t i)            { set(i); }
ValueValue62         explicit Value(int64_t i)            { set(i); }
ValueValue63         explicit Value(const AString &i)     { set(i); }
ValueValue64         explicit Value(const sp<ABuffer> &i) { set(i); }
65     };
66 
67     struct Dict : public std::map<std::string, Value> {
68         Dict() = default;
69         std::string debugString(size_t indent = 0) const;
70     };
71 
72     /**
73      * Enumerates all fields of the parameter descriptors supplied, so that this opbject can later
74      * query and update these.
75      *
76      * For now only first-level fields are supported. Also, array fields are not supported.
77      *
78      * \param reflector   C2ParamReflector object for C2Param reflection.
79      * \param paramDescs  vector of C2ParamDescriptor objects that this object
80      *                    would recognize when building params.
81      */
82     void addParamDesc(
83             const std::shared_ptr<C2ParamReflector> &reflector,
84             const std::vector<std::shared_ptr<C2ParamDescriptor>> &paramDescs);
85 
86     /**
87      * Adds fields of a standard parameter (that may not be supported by the parameter reflector
88      * or may not be listed as a supported value by the component). If the parameter name is
89      * used for another parameter, this operation is a no-op. (Technically, this is by fields).
90      *
91      * \param T standard parameter type
92      * \param name parameter name
93      */
94     template<typename T>
95     void addStandardParam(const std::string &name, C2ParamDescriptor::attrib_t attrib =
96                           C2ParamDescriptor::IS_READ_ONLY) {
97         addParamDesc(std::make_shared<C2ParamDescriptor>(
98                 C2Param::Index(T::PARAM_TYPE), attrib, name.c_str()),
99                 C2StructDescriptor((T*)nullptr), nullptr /* descriptor */);
100     }
101 
102     /**
103      * Adds fields of a structure (or a parameater) described by the struct descriptor. If
104      * reflector is provided, fields of sub-structures are also added. Otherwise, only top-level
105      * fundamental typed fields (arithmetic, string and blob) are added.
106      *
107      * \param paramDesc parameter descriptor
108      * \param fieldDesc field descriptor
109      * \param path path/name of the structure (field or parent parameter)
110      * \param offset offset of the structure in the parameter
111      * \param reflector  C2ParamReflector object for C2Param reflection (may be null)
112      */
113     void addParamStructDesc(
114             std::shared_ptr<C2ParamDescriptor> paramDesc, C2String path, size_t offset,
115             const C2StructDescriptor &structDesc,
116             const std::shared_ptr<C2ParamReflector> &reflector);
117 
118     /**
119      * Adds fields of a parameter described by the struct descriptor. If reflector is provided,
120      * fields of sub-structures are also added. Otherwise, only top-level fundamental typed fields
121      * (arithmetic, string and blob) are added.
122      *
123      * \param paramDesc parameter descriptor
124      * \param fieldDesc field descriptor
125      * \param reflector  C2ParamReflector object for C2Param reflection (may be null)
126      * \param markVendor TEMP if true, prefix vendor parameter names with "vendor."
127      */
128     void addParamDesc(
129             std::shared_ptr<C2ParamDescriptor> paramDesc, const C2StructDescriptor &structDesc,
130             const std::shared_ptr<C2ParamReflector> &reflector,
131             bool markVendor = true);
132 
133     /**
134      * Add support for setting a parameter as a binary blob.
135      *
136      * \param name name of the parameter
137      * \param coreIndex parameter (core) index
138      */
139     void supportWholeParam(std::string name, C2Param::CoreIndex coreIndex);
140 
141     /**
142      * Returns the name of the parameter for an index.
143      */
144     std::string getParamName(C2Param::Index index) const;
145 
146     /**
147      * Get list of param indices from field names and values in AMessage object.
148      *
149      * TODO: This should be in the order that they are listed by the component.
150      *
151      * \param params[in]  Dict object with field name to value pairs.
152      * \param vec[out]    vector to store the indices from |params|.
153      */
154     void getParamIndicesFromMessage(
155             const Dict &params,
156             std::vector<C2Param::Index> *vec /* nonnull */) const;
157 
158     /**
159      * Get list of param indices from field names (only) in AMessage object.
160      *
161      * \param params[in]  Vector object with field names.
162      * \param vec[out]    vector to store the indices from |params|.
163      */
164     void getParamIndicesForKeys(
165             const std::vector<std::string> &keys,
166             std::vector<C2Param::Index> *vec /* nonnull */) const;
167 
168     /**
169      * Update C2Param objects from field name and value in AMessage object.
170      *
171      * \param params[in]    Dict object with field name to value pairs.
172      * \param vec[in,out]   vector of the C2Param objects to be updated.
173      */
174     void updateParamsFromMessage(
175             const Dict &params,
176             std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const;
177 
178     /**
179      * Get fields from C2Param objects in AMessage object.
180      *
181      * \param params[in]    vector of the C2Param objects to be queried
182      * \return a Dict object containing the known parameters
183      */
184     Dict getParams(
185             const std::vector<C2Param*> &params /* nonnull */) const;
186 
187     Dict getParams(
188             const std::vector<std::unique_ptr<C2Param>> &params /* nonnull */) const;
189 
190     /**
191      * Clear param descriptors in this object.
192      */
193     void clear();
194 
195 private:
196     struct FieldDesc {
197         std::shared_ptr<C2ParamDescriptor> paramDesc;
198         std::unique_ptr<C2FieldDescriptor> fieldDesc;
199         size_t offset;
200     };
201     std::map<std::string, FieldDesc> mMap;
202     std::map<C2Param::Index, std::string> mParamNames;
203     std::map<std::string, C2Param::CoreIndex> mWholeParams;
204 
205     void parseMessageAndDoWork(
206             const Dict &params,
207             std::function<void(const std::string &, const FieldDesc &, const void *, size_t)> work) const;
208 
209     C2_DO_NOT_COPY(ReflectedParamUpdater);
210 };
211 
212 }  // namespace android
213 
214 #endif  // REFLECTED_PARAM_BUILDER_H_
215