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      * Returns the name of the parameter for an index.
135      */
136     std::string getParamName(C2Param::Index index) const;
137 
138     /**
139      * Get list of param indices from field names and values in AMessage object.
140      *
141      * TODO: This should be in the order that they are listed by the component.
142      *
143      * \param params[in]  Dict object with field name to value pairs.
144      * \param vec[out]    vector to store the indices from |params|.
145      */
146     void getParamIndicesFromMessage(
147             const Dict &params,
148             std::vector<C2Param::Index> *vec /* nonnull */) const;
149 
150     /**
151      * Get list of param indices from field names (only) in AMessage object.
152      *
153      * \param params[in]  Vector object with field names.
154      * \param vec[out]    vector to store the indices from |params|.
155      */
156     void getParamIndicesForKeys(
157             const std::vector<std::string> &keys,
158             std::vector<C2Param::Index> *vec /* nonnull */) const;
159 
160     /**
161      * Update C2Param objects from field name and value in AMessage object.
162      *
163      * \param params[in]    Dict object with field name to value pairs.
164      * \param vec[in,out]   vector of the C2Param objects to be updated.
165      */
166     void updateParamsFromMessage(
167             const Dict &params,
168             std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const;
169 
170     /**
171      * Get fields from C2Param objects in AMessage object.
172      *
173      * \param params[in]    vector of the C2Param objects to be queried
174      * \return a Dict object containing the known parameters
175      */
176     Dict getParams(
177             const std::vector<C2Param*> &params /* nonnull */) const;
178 
179     Dict getParams(
180             const std::vector<std::unique_ptr<C2Param>> &params /* nonnull */) const;
181 
182     /**
183      * Clear param descriptors in this object.
184      */
185     void clear();
186 
187 private:
188     struct FieldDesc {
189         std::shared_ptr<C2ParamDescriptor> paramDesc;
190         std::unique_ptr<C2FieldDescriptor> fieldDesc;
191         size_t offset;
192     };
193     std::map<std::string, FieldDesc> mMap;
194     std::map<C2Param::Index, std::string> mParamNames;
195 
196     void parseMessageAndDoWork(
197             const Dict &params,
198             std::function<void(const std::string &, const FieldDesc &, const void *, size_t)> work) const;
199 
200     C2_DO_NOT_COPY(ReflectedParamUpdater);
201 };
202 
203 }  // namespace android
204 
205 #endif  // REFLECTED_PARAM_BUILDER_H_
206