1 /*
2  * Copyright (C) 2019 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 ANDROID_MEDIA_ECO_DATA_H_
18 #define ANDROID_MEDIA_ECO_DATA_H_
19 
20 #include <binder/Parcel.h>
21 #include <binder/Parcelable.h>
22 
23 #include <string>
24 #include <unordered_map>
25 #include <variant>
26 
27 namespace android {
28 namespace media {
29 namespace eco {
30 
31 enum class ECODataStatus {
32     OK,
33     FAIL_TO_INSERT,
34     INVALID_ECODATA_TYPE,
35     KEY_NOT_EXIST,
36     INVALID_VALUE_TYPE,
37     INVALID_ARGUMENT,
38 };
39 
40 /**
41 * ECOData is the container for all messages passed between different components in ECOService.
42 * All messages in ECOServices are represented by a list of key-value pairs.
43 * For example:
44 *     "bit-rate" -> 22000000
45 *     "Provider-Name" -> "QCOM-Video-Encoder".
46 *     "avg-frame-qp" -> 40
47 * ECOData follows the same design pattern of AMessage and Metadata in Media Framework. The key
48 * must be non-empty string. Below are the supported data types:
49 *
50 *    //   Item types      set/find function suffixes
51 *    //   ==========================================
52 *    //     int32_t                Int32
53 *    //     int64_t                Int64
54 *    //     size_t                 Size
55 *    //     float                  Float
56 *    //     double                 Double
57 *    //     String                 String
58 *
59 * ECOData does not support duplicate keys with different values. When inserting a key-value pair,
60 * a new entry will be created if the key does not exist. Othewise, they key's value will be
61 * overwritten with the new value.
62 *
63 *  Sample usage:
64 *
65 *   // Create the ECOData
66 *   std::unique_ptr<ECOData> data = std::make_unique<ECOData>(ECOData::DATA_TYPE_STATS, 1000);
67 *
68 *   // Set the encoder name.
69 *   data->setString("stats-encoder-type", "google-avc");
70 *
71 *   // Set encoding bitrate.
72 *   data->setInt32("stats-encoder-target-bitrate-bps", 22000000);
73 */
74 class ECOData : public Parcelable {
75 public:
76     using ECODataValueType =
77             std::variant<int32_t, int64_t, size_t, float, double, std::string, int8_t>;
78     using ECODataKeyValuePair = std::pair<std::string, ECODataValueType>;
79 
ECOData()80     ECOData() : mDataType(0), mDataTimeUs(-1) {}
ECOData(int32_t type)81     ECOData(int32_t type) : mDataType(type), mDataTimeUs(-1) {}
ECOData(int32_t type,int64_t timeUs)82     ECOData(int32_t type, int64_t timeUs) : mDataType(type), mDataTimeUs(timeUs) {}
83 
84     // Constants for mDataType.
85     typedef enum {
86         DATA_TYPE_UNKNOWN = 0,
87         /* Data sent from the ECOServiceStatsProvider to ECOService. */
88         DATA_TYPE_STATS = 1,
89         /* Data sent from the ECOService to ECOServiceInfoListener. */
90         DATA_TYPE_INFO = 2,
91         /* Configuration data sent by ECOServiceStatsProvider when connects with ECOService. */
92         DATA_TYPE_STATS_PROVIDER_CONFIG = 3,
93         /* Configuration data sent by ECOServiceInfoListener when connects with ECOService. */
94         DATA_TYPE_INFO_LISTENER_CONFIG = 4,
95     } ECODatatype;
96 
97     // set/find functions that could be used for all the value types.
98     ECODataStatus set(const std::string& key, const ECODataValueType& value);
99     ECODataStatus find(const std::string& key, ECODataValueType* out) const;
100 
101     // Convenient set/find functions for string value type.
102     ECODataStatus setString(const std::string& key, const std::string& value);
103     ECODataStatus findString(const std::string& key, std::string* out) const;
104 
105     // Convenient set/find functions for int32_t value type.
106     ECODataStatus setInt32(const std::string& key, int32_t value);
107     ECODataStatus findInt32(const std::string& key, int32_t* out) const;
108 
109     // Convenient set/find functions for int64_t value type.
110     ECODataStatus setInt64(const std::string& key, int64_t value);
111     ECODataStatus findInt64(const std::string& key, int64_t* out) const;
112 
113     // Convenient set/find functions for float value type.
114     ECODataStatus setFloat(const std::string& key, float value);
115     ECODataStatus findFloat(const std::string& key, float* out) const;
116 
117     // Convenient set/find functions for double value type.
118     ECODataStatus setDouble(const std::string& key, double value);
119     ECODataStatus findDouble(const std::string& key, double* out) const;
120 
121     // Convenient set/find functions for size_t value type.
122     ECODataStatus setSize(const std::string& key, size_t value);
123     ECODataStatus findSize(const std::string& key, size_t* out) const;
124 
125     // Convenient set/find functions for int8_t value type.
126     // TODO(hkuang): Add unit test.
127     ECODataStatus setInt8(const std::string& key, int8_t value);
128     ECODataStatus findInt8(const std::string& key, int8_t* out) const;
129 
130     /**
131     * Serialization over Binder
132     */
133     status_t readFromParcel(const Parcel* parcel) override;
134     status_t writeToParcel(Parcel* parcel) const override;
135 
136     /* Returns the type of the data. */
137     int32_t getDataType() const;
138 
139     /* Returns the type of the data in string. */
140     std::string getDataTypeString() const;
141 
142     /* Returns the timestamp associated with the data. */
143     int64_t getDataTimeUs() const;
144 
145     /* Sets the type of the data. */
146     void setDataType(int32_t type);
147 
148     /* Sets the timestamp associated with the data. */
149     void setDataTimeUs();
150 
151     /* Gets the number of keys in the ECOData. */
getNumOfEntries()152     size_t getNumOfEntries() const { return mKeyValueStore.size(); }
153 
154     /* Whether the ECOData is empty. */
isEmpty()155     size_t isEmpty() const { return mKeyValueStore.size() == 0; }
156 
157     friend class ECODataKeyValueIterator;
158 
159     friend bool copyKeyValue(const ECOData& src, ECOData* dst);
160 
161     // Dump the ECOData as a string.
162     std::string debugString() const;
163 
164 protected:
165     // ValueType. This must match the index in ECODataValueType.
166     enum ValueType {
167         kTypeInt32 = 0,
168         kTypeInt64 = 1,
169         kTypeSize = 2,
170         kTypeFloat = 3,
171         kTypeDouble = 4,
172         kTypeString = 5,
173         kTypeInt8 = 6,
174     };
175 
176     /* The type of the data */
177     int32_t mDataType;
178 
179     // The timestamp time associated with the data in microseconds. The timestamp should be in
180     // boottime time base. This is only used when the data type is stats or info. -1 means
181     // unavailable.
182     int64_t mDataTimeUs;
183 
184     // Internal store for the key value pairs.
185     std::unordered_map<std::string, ECODataValueType> mKeyValueStore;
186 
187     template <typename T>
188     ECODataStatus setValue(const std::string& key, T value);
189 
190     template <typename T>
191     ECODataStatus findValue(const std::string& key, T* out) const;
192 };
193 
194 // A simple ECOData iterator that will iterate over all the key value paris in ECOData.
195 // To be used like:
196 // while (it.hasNext()) {
197 //   entry = it.next();
198 // }
199 class ECODataKeyValueIterator {
200 public:
ECODataKeyValueIterator(const ECOData & data)201     ECODataKeyValueIterator(const ECOData& data)
202           : mKeyValueStore(data.mKeyValueStore), mBeginReturned(false) {
203         mIterator = mKeyValueStore.begin();
204     }
205     ~ECODataKeyValueIterator() = default;
206     bool hasNext();
207     ECOData::ECODataKeyValuePair next() const;
208 
209 private:
210     const std::unordered_map<std::string, ECOData::ECODataValueType>& mKeyValueStore;
211     std::unordered_map<std::string, ECOData::ECODataValueType>::const_iterator mIterator;
212     bool mBeginReturned;
213 };
214 
215 }  // namespace eco
216 }  // namespace media
217 }  // namespace android
218 
219 #endif  // ANDROID_MEDIA_ECO_DATA_H_
220