xref: /aosp_15_r20/system/media/audio_utils/include/audio_utils/Metadata.h (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1 /*
2  * Copyright 2020 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_AUDIO_METADATA_H
18 #define ANDROID_AUDIO_METADATA_H
19 
20 #include <stdint.h>
21 #include <sys/cdefs.h>
22 #include <unistd.h>
23 
24 #ifdef __cplusplus
25 
26 #include "template_utils.h"
27 
28 #include <algorithm>
29 #include <any>
30 #include <map>
31 #include <string>
32 #include <tuple>
33 #include <vector>
34 
35 /**
36  * Audio Metadata: a C++ Object based map.
37  *
38  * Data is a map of strings to Datum Objects.
39  *
40  * Datum is a C++ "Object", a direct instance of std::any, but limited
41  * to only the following allowed types:
42  *
43  * Native                              Java equivalent
44  * int32                               (int)
45  * int64                               (long)
46  * float                               (float)
47  * double                              (double)
48  * std::string                         (String)
49  * Data (std::map<std::string, Datum>) (Map<String, Object>)
50  *
51  * Metadata code supports advanced automatic parceling.
52  * TEST ONLY:
53  * std::vector<Datum>                  (Object[])             --> vector of Objects
54  * std::pair<Datum, Datum>             (Pair<Object, Object>) --> pair of Objects
55  * std::vector<std::vector<std::pair<std::string, short>>>    --> recursive containers
56  * struct { int i0; std::vector<int> v1; std::pair<int, int> p2; } --> struct parceling
57  *
58  * The Data map accepts typed Keys, which designate the type T of the
59  * value associated with the Key<T> in the template parameter.
60  *
61  * CKey<T> is the constexpr version suitable for fixed compile-time constants.
62  * Key<T> is the non-constexpr version.
63  *
64  * Notes: for future extensibility:
65  *
66  * In order to add a new type in.
67  *
68  * 1) Add the new type to the END of the metadata_types lists below.
69  *
70  * 2) The new type can be a primitive, or make use of containers std::map, std::vector,
71  * std::pair, or be simple structs (see below).
72  *
73  * 3) Simple structs contain no pointers and all public data. The members can be based
74  * on existing types.
75  *   a) If trivially copyable (packed) primitive data,
76  *      add to primitive_metadata_types.
77  *   b) If the struct requires member-wise parceling, add to structural_metadata_types
78  *      (current limit is 4 members).
79  *
80  * 4) The type system is recursive.
81  *
82  * Design notes:
83  * 1) Tuple is intentionally not implemented as it isn't that readable.  This can
84  * be revisited if the need comes up.  If you have more than a couple of elements,
85  * we suggest embedding in a Data typed map or a Simple struct.
86  *
87  * 2) Each custom type e.g. vector<int>, pair<short, char> takes one
88  * slot in the type index.  A full type description language is not implemented
89  * here for brevity and clarity.
90  */
91 
92 namespace android::audio_utils::metadata {
93 
94 using android::audio_utils::is_specialization_v;
95 using android::audio_utils::is_braces_constructible;
96 
97 // Set up type comparison system
98 // see std::variant for the how the type_index() may be used.
99 
100 /*
101  * returns the index of type T in the type parameter list Ts.
102  */
103 template <typename T, typename... Ts>
type_index()104 inline constexpr ssize_t type_index() {
105     constexpr bool checks[] = {std::is_same_v<std::decay_t<T>, std::decay_t<Ts>>...};
106     for (size_t i = 0; i < sizeof...(Ts); ++i) {
107         if (checks[i]) return i; // the index in Ts.
108     }
109     return -1; // none found.
110 }
111 
112 // compound_type is a holder of types. There are concatenation tricks of type lists
113 // but we don't need them here.
114 template <typename... Ts>
115 struct compound_type {
116     inline static constexpr size_t size_v = sizeof...(Ts);
117     template <typename T>
118     inline static constexpr bool contains_v = type_index<T, Ts...>() >= 0;
119     template <typename T>
index_ofcompound_type120     inline static constexpr ssize_t index_of() { return type_index<T, Ts...>(); }
121 
122     // create a tupe equivalent of the compound type. This is useful for
123     // finding the nth type by std::tuple_element
124     using tuple_t = std::tuple<Ts...>;
125 
126     /**
127      * Applies function f to a datum pointer a.
128      *
129      * \param f is the function to apply.  It should take one argument,
130      *     which is a (typed) pointer to the value stored in a.
131      * \param a is the Datum object (derived from std::any).
132      * \param result if non-null stores the return value of f (if f has a return value).
133      *     result may be nullptr if one does not care about the return value of f.
134      * \return true on success, false if there is no applicable data stored in a.
135      */
136     template <typename F, typename A>
137     static bool apply(F f, A *a, std::any *result = nullptr) {
138         return apply_impl<F, A, Ts...>(f, a, result);
139     }
140 
141     // helper
142     // Linear search in the number of types because of non-cached std:any_cast
143     // lookup.  See std::visit for std::variant for constant time implementation.
144     template <typename F, typename A, typename T, typename... Ts2>
apply_implcompound_type145     static bool apply_impl(F f, A *a, std::any *result) {
146         auto t = std::any_cast<T>(a); // may be const ptr or not.
147         if (t == nullptr) {
148             return apply_impl<F, A, Ts2...>(f, a, result);
149         }
150 
151         // only save result if the function has a non-void return type.
152         // and result is not nullptr.
153         using result_type = std::invoke_result_t<F, T*>;
154         if constexpr (!std::is_same_v<result_type, void>) {
155             if (result != nullptr) {
156                 *result = (result_type)f(t);
157                 return true;
158             }
159         }
160 
161         f(t); // discard the result
162         return true;
163     }
164 
165     // helper base class
166     template <typename F, typename A>
apply_implcompound_type167     static bool apply_impl(F f __attribute__((unused)), A *a __attribute__((unused)),
168             std::any *result __attribute__((unused))) {
169         return false;
170     }
171 };
172 
173 #ifdef METADATA_TESTING
174 
175 // This is a helper struct to verify that we are moving Datums instead
176 // of copying them.
177 struct MoveCount {
178     int32_t mMoveCount = 0;
179     int32_t mCopyCount = 0;
180 
181     MoveCount() = default;
MoveCountMoveCount182     MoveCount(MoveCount&& other) {
183         mMoveCount = other.mMoveCount + 1;
184         mCopyCount = other.mCopyCount;
185     }
MoveCountMoveCount186     MoveCount(const MoveCount& other) {
187         mMoveCount = other.mMoveCount;
188         mCopyCount = other.mCopyCount + 1;
189     }
190     MoveCount &operator=(MoveCount&& other) {
191         mMoveCount = other.mMoveCount + 1;
192         mCopyCount = other.mCopyCount;
193         return *this;
194     }
195     MoveCount &operator=(const MoveCount& other) {
196         mMoveCount = other.mMoveCount;
197         mCopyCount = other.mCopyCount + 1;
198         return *this;
199     }
200 };
201 
202 // We can automatically parcel this "Arbitrary" struct
203 // since it has no pointers and all public members.
204 struct Arbitrary {
205     int i0;
206     std::vector<int> v1;
207     std::pair<int, int> p2;
208 };
209 
210 #endif
211 
212 class Data;
213 class Datum;
214 
215 // The order of this list must be maintained for binary compatibility
216 using metadata_types = compound_type<
217     int32_t,
218     int64_t,
219     float,
220     double,
221     std::string,
222     Data /* std::map<std::string, Datum> */
223     // OK to add at end.
224 #ifdef METADATA_TESTING
225     , std::vector<Datum>      // another complex object for testing
226     , std::pair<Datum, Datum> // another complex object for testing
227     , std::vector<std::vector<std::pair<std::string, short>>> // complex object
228     , MoveCount
229     , Arbitrary
230 #endif
231     >;
232 
233 // A subset of the metadata types may be directly copied as bytes
234 using primitive_metadata_types = compound_type<int32_t, int64_t, float, double
235 #ifdef METADATA_TESTING
236     , MoveCount
237 #endif
238     >;
239 
240 // A subset of metadata types which are a struct-based.
241 using structural_metadata_types = compound_type<
242 #ifdef METADATA_TESTING
243     Arbitrary
244 #endif
245     >;
246 
247 template <typename T>
248 inline constexpr bool is_primitive_metadata_type_v =
249     primitive_metadata_types::contains_v<T>;
250 
251 template <typename T>
252 inline constexpr bool is_structural_metadata_type_v =
253     structural_metadata_types::contains_v<T>;
254 
255 template <typename T>
256 inline constexpr bool is_metadata_type_v =
257     metadata_types::contains_v<T>;
258 
259 /**
260  * Datum is the C++ version of Object, based on std::any
261  * to be portable to other Data Object systems on std::any. For C++, there
262  * are two forms of generalized Objects, std::variant and std::any.
263  *
264  * What is a variant?
265  * std::variant is like a std::pair<type_index, union>, where the types
266  * are kept in the template parameter list, and you only need to store
267  * the type_index of the current value's type in the template parameter
268  * list to find the value's type (to access data in the union).
269  *
270  * What is an any?
271  * std::any is a std::pair<type_func, pointer> (though the standard encourages
272  * small buffer optimization of the pointer for small data types,
273  * so the pointer might actually be data).  The type_func is cleverly
274  * implemented templated, so that one type_func exists per type.
275  *
276  * For datum, we use std::any, which is different than mediametrics::Item
277  * (which uses std::variant).
278  *
279  * std::any is the C++ version of Java's Object.  One benefit of std::any
280  * over std::variant is that it is portable outside of this package as a
281  * std::any, to another C++ Object system based on std::any
282  * (as we any_cast to discover the type). std::variant does not have this
283  * portability (without copy conversion) because it requires an explicit
284  * type list to be known in the template, so you can't exchange them freely
285  * as the union size and the type/type ordering will be different in general
286  * between two variant-based Object systems.
287  *
288  * std::any may work better with some recursive types than variants,
289  * as it uses pointers so that physical size need not be known for type
290  * definition.
291  *
292  * This is a design choice: mediametrics::Item as a closed system,
293  * metadata::Datum as an open system.
294  *
295  * CAUTION:
296  * For efficiency, prefer the use of std::any_cast<T>(std::any *)
297  *       which returns a pointer to T (no extra copies.)
298  *
299  * std::any_cast<T>(std::any) returns an instance of T (copy constructor).
300  * std::get<N>(std::variant) returns a reference (no extra copies).
301  *
302  * The Data map operations are optimized to return references to
303  * avoid unnecessary copies.
304  */
305 
306 class Datum : public std::any {
307 public:
308     // Don't add any virtual functions or non-static member variables.
309 
310     Datum() = default;
311 
312     // Do not make these explicit
313     // Force type of std::any to exactly the values we permit to be parceled.
314     template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
Datum(T && t)315     Datum(T && t) : std::any(std::forward<T>(t)) {};
316 
317     template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
318     Datum& operator=(T&& t) {
319         static_cast<std::any *>(this)->operator=(std::forward<T>(t));
320         return *this;
321     }
322 
Datum(const char * t)323     Datum(const char *t) : std::any(std::string(t)) {}; // special string handling
324 };
325 
326 // PREVENT INCORRECT MODIFICATIONS
327 // Datum is a helping wrapper on std::any
328 // Don't add any non-static members
329 static_assert(sizeof(Datum) == sizeof(std::any));
330 // Nothing is virtual
331 static_assert(!std::is_polymorphic_v<Datum>);
332 
333 /**
334  * Keys
335  *
336  * Audio Metadata keys are typed.  Similar to variant's template typenames,
337  * which directly indicate possible types in the union, the Audio Metadata
338  * Keys contain the Value's Type in the Key's template type parameter.
339  *
340  * Example:
341  *
342  * inline constexpr CKey<int64_t> MY_BIGINT("bigint_is_mine");
343  * inline constexpr CKey<Data> TABLE("table");
344  *
345  * Thus if we have a Data object d:
346  *
347  * decltype(d[TABLE]) is Data
348  * decltype(d[MY_BIGINT) is int64_t
349  */
350 
351 /**
352  * Key is a non-constexpr key which has local storage in a string.
353  */
354 template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
355 class Key : private std::string {
356 public:
357     using std::string::string; // base constructor
getName()358     const char *getName() const { return c_str(); }
359 };
360 
361 /**
362  * CKey is a constexpr key, which is preferred.
363  *
364  * inline constexpr CKey<int64_t> MY_BIGINT("bigint_is_mine");
365  */
366 template <typename T, typename = std::enable_if_t<is_metadata_type_v<T>>>
367 class CKey  {
368     const char * const mName;
369 public:
CKey(const char * name)370     explicit constexpr CKey(const char *name) : mName(name) {}
CKey(const Key<T> & key)371     CKey(const Key<T> &key) : mName(key.getName()) {}
getName()372     const char *getName() const { return mName; }
373 };
374 
375 /**
376  * Data is the storage for our Datums.
377  *
378  * It is implemented on top of std::map<std::string, Datum>
379  * but we augment it with typed Key
380  * getters and setters, as well as operator[] overloads.
381  */
382 class Data : public std::map<std::string, Datum> {
383 public:
384     // Don't add any virtual functions or non-static member variables.
385 
386     // We supplement the raw form of map with
387     // the following typed form using Key.
388 
389     // Intentionally there is no get(), we suggest *get_ptr()
390     template <template <typename /* T */, typename... /* enable-ifs */> class K, typename T>
391     T* get_ptr(const K<T>& key, bool allocate = false) {
392         auto it = find(key.getName());
393         if (it == this->end()) {
394             if (!allocate) return nullptr;
395             it = emplace(key.getName(), T{}).first;
396         }
397         return std::any_cast<T>(&it->second);
398     }
399 
400     template <template <typename, typename...> class K, typename T>
get_ptr(const K<T> & key)401     const T* get_ptr(const K<T>& key) const {
402         auto it = find(key.getName());
403         if (it == this->end()) return nullptr;
404         return std::any_cast<T>(&it->second);
405     }
406 
407     template <template <typename, typename...> class K, typename T>
put(const K<T> & key,T && t)408     void put(const K<T>& key, T && t) {
409         (*this)[key.getName()] = std::forward<T>(t);
410     }
411 
412     template <template <typename, typename...> class K>
put(const K<std::string> & key,const char * value)413     void put(const K<std::string>& key, const char *value) {
414         (*this)[key.getName()] = value;
415     }
416 
417     // We overload our operator[] so we unhide the one in the base class.
418     using std::map<std::string, Datum>::operator[];
419 
420     template <template <typename, typename...> class K, typename T>
421     T& operator[](const K<T> &key) {
422         return *get_ptr(key, /* allocate */ true);
423     }
424 
425     template <template <typename, typename...> class K, typename T>
426     const T& operator[](const K<T> &key) const {
427         return *get_ptr(key);
428     }
429 };
430 
431 // PREVENT INCORRECT MODIFICATIONS
432 // Data is a helping wrapper on std::map
433 // Don't add any non-static members
434 static_assert(sizeof(Data) == sizeof(std::map<std::string, Datum>));
435 // Nothing is virtual
436 static_assert(!std::is_polymorphic_v<Data>);
437 
438 /**
439  * Parceling of Datum by recursive descent to a ByteString
440  *
441  * Parceling Format:
442  * All values are native endian order.
443  *
444  * Datum = {
445  *           (type_size_t)  Type (the type index from type_as_value<T>.)
446  *           (datum_size_t) Size (size of Payload)
447  *           (byte string)  Payload<Type>
448  *         }
449  *
450  * Payload<Primitive_Type> = { bytes in native endian order }
451  *
452  * Payload<String> = { (index_size_t) number of elements (not including zero termination)
453  *                     bytes of string data.
454  *                   }
455  *
456  * Vector, Map, Container types:
457  * Payload<Type> = { (index_size_t) number of elements
458  *                   (byte string)  Payload<Element_Type> * number
459  *                 }
460  *
461  * Pair container types:
462  * Payload<Type> = { (byte string) Payload<first>,
463  *                   (byte string) Payload<second>
464  *                 }
465  *
466  * Note: Data is a std::map<std::string, Datum>
467  *
468  * Design notes:
469  *
470  * 1) The size of each datum allows skipping of unknown types for compatibility
471  * of older code with newer Datums.
472  *
473  * Examples:
474  * Payload<Int32> of 123
475  * [ value of 123                   ] =  0x7b 0x00 0x00 0x00       123
476  *
477  * Example of Payload<String> of std::string("hi"):
478  * [ (index_size_t) length          ] = 0x02 0x00 0x00 0x00        2 strlen("hi")
479  * [ raw bytes "hi"                 ] = 0x68 0x69                  "hi"
480  *
481  * Payload<Data>
482  * [ (index_size_t) entries ]
483  * [ raw bytes   (entry 1) Key   (Payload<String>)
484  *                         Value (Datum)
485  *                ...  (until #entries) ]
486  *
487  * Example of Payload<Data> of {{"hello", "world"},
488  *                              {"value", (int32_t)1000}};
489  * [ (index_size_t) #entries        ] = 0x02 0x00 0x00 0x00        2 entries
490  *    Key (Payload<String>)
491  *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("hello")
492  *    [ raw bytes "hello"           ] = 0x68 0x65 0x6c 0x6c 0x6f   "hello"
493  *    Value (Datum)
494  *    [ (type_size_t) type          ] = 0x05 0x00 0x00 0x00        5 (TYPE_STRING)
495  *    [ (datum_size_t) size         ] = 0x09 0x00 0x00 0x00        sizeof(index_size_t) +
496  *                                                                 strlen("world")
497  *       Payload<String>
498  *       [ (index_size_t) length    ] = 0x05 0x00 0x00 0x00        5 strlen("world")
499  *       [ raw bytes "world"        ] = 0x77 0x6f 0x72 0x6c 0x64   "world"
500  *    Key (Payload<String>)
501  *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("value")
502  *    [ raw bytes "value"           ] = 0x76 0x61 0x6c 0x75 0x65   "value"
503  *    Value (Datum)
504  *    [ (type_size_t) type          ] = 0x01 0x00 0x00 0x00        1 (TYPE_INT32)
505  *    [ (datum_size_t) size         ] = 0x04 0x00 0x00 0x00        4 sizeof(int32_t)
506  *        Payload<Int32>
507  *        [ raw bytes 1000          ] = 0xe8 0x03 0x00 0x00        1000
508  *
509  * Metadata is passed as a Payload<Data>.
510  * An implementation dependent detail is that the Keys are always
511  * stored sorted, so the byte string representation generated is unique.
512  */
513 
514 // Platform Apex compatibility note:
515 // type_size_t may not change.
516 using type_size_t = uint32_t;
517 
518 // Platform Apex compatibility note:
519 // index_size_t must not change.
520 using index_size_t = uint32_t;
521 
522 // Platform Apex compatibility note:
523 // datum_size_t must not change.
524 using datum_size_t = uint32_t;
525 
526 // The particular implementation of ByteString may change
527 // without affecting compatibility.
528 using ByteString = std::vector<uint8_t>;
529 
530 /*
531     These should correspond to the Java AudioMetadata.java
532 
533     Permitted type indexes:
534 
535     TYPE_NONE = 0,
536     TYPE_INT32 = 1,
537     TYPE_INT64 = 2,
538     TYPE_FLOAT = 3,
539     TYPE_DOUBLE = 4,
540     TYPE_STRING = 5,
541     TYPE_DATA = 6,
542 */
543 
544 template <typename T>
get_type_as_value()545 inline constexpr type_size_t get_type_as_value() {
546     return (type_size_t)(metadata_types::index_of<T>() + 1);
547 }
548 
549 template <typename T>
550 inline constexpr type_size_t type_as_value = get_type_as_value<T>();
551 
552 // forward decl for recursion - do not remove.
553 bool copyToByteString(const Datum& datum, ByteString &bs);
554 
555 template <template <typename ...> class V, typename... Args>
556 bool copyToByteString(const V<Args...>& v, ByteString&bs);
557 // end forward decl
558 
559 // primitives handled here
560 template <typename T>
561 std::enable_if_t<
562     is_primitive_metadata_type_v<T> || std::is_arithmetic_v<std::decay_t<T>>,
563     bool
564     >
copyToByteString(const T & t,ByteString & bs)565 copyToByteString(const T& t, ByteString& bs) {
566     bs.insert(bs.end(), (uint8_t*)&t, (uint8_t*)&t + sizeof(t));
567     return true;
568 }
569 
570 // pairs handled here
571 template <typename A, typename B>
copyToByteString(const std::pair<A,B> & p,ByteString & bs)572 bool copyToByteString(const std::pair<A, B>& p, ByteString& bs) {
573     return copyToByteString(p.first, bs) && copyToByteString(p.second, bs);
574 }
575 
576 // containers
577 template <template <typename ...> class V, typename... Args>
copyToByteString(const V<Args...> & v,ByteString & bs)578 bool copyToByteString(const V<Args...>& v, ByteString& bs) {
579     if (v.size() > std::numeric_limits<index_size_t>::max()) return false;
580     index_size_t size = v.size();
581     if (!copyToByteString(size, bs)) return false;
582     if constexpr (std::is_same_v<std::decay_t<V<Args...>>, std::string>) {
583         bs.insert(bs.end(), (uint8_t*)v.c_str(), (uint8_t*)v.c_str() + v.size());
584     }  else /* constexpr */ {
585         for (const auto &d : v) { // handles std::vector and std::map
586             if (!copyToByteString(d, bs)) return false;
587         }
588     }
589     return true;
590 }
591 
592 // simple struct data (use structured binding to extract members)
593 template <typename T>
594 std::enable_if_t<
595     is_structural_metadata_type_v<T>,
596     bool
597     >
copyToByteString(const T & t,ByteString & bs)598 copyToByteString(const T& t, ByteString& bs) {
599     using type = std::decay_t<T>;
600     if constexpr (is_braces_constructible<type, any_type, any_type, any_type, any_type>{}) {
601         const auto& [e1, e2, e3, e4] = t;
602         return copyToByteString(e1, bs)
603             && copyToByteString(e2, bs)
604             && copyToByteString(e3, bs)
605             && copyToByteString(e4, bs);
606     } else if constexpr (is_braces_constructible<type, any_type, any_type, any_type>{}) {
607         const auto& [e1, e2, e3] = t;
608         return copyToByteString(e1, bs)
609             && copyToByteString(e2, bs)
610             && copyToByteString(e3, bs);
611     } else if constexpr (is_braces_constructible<type, any_type, any_type>{}) {
612         const auto& [e1, e2] = t;
613         return copyToByteString(e1, bs)
614             && copyToByteString(e2, bs);
615     } else if constexpr(is_braces_constructible<type, any_type>{}) {
616         const auto& [e1] = t;
617         return copyToByteString(e1, bs);
618     } else if constexpr (is_braces_constructible<type>{}) {
619         return true; // like std::monostate - no members
620     } else /* constexpr */ {
621         static_assert(dependent_false_v<T>);
622     }
623 }
624 
625 // TODO Consider moving to .cpp, but one advantage of keeping in the header
626 // is that C++ invocations don't need to link with the shared library.
627 
628 // Datum
629 inline
copyToByteString(const Datum & datum,ByteString & bs)630 bool copyToByteString(const Datum& datum, ByteString &bs) {
631     bool success = false;
632     return metadata_types::apply([&bs, &success](auto ptr) {
633              // save type
634              const type_size_t type = type_as_value<decltype(*ptr)>;
635              if (!copyToByteString(type, bs)) return;
636 
637              // get current location
638              const size_t idx = bs.size();
639 
640              // save size (replaced later)
641              datum_size_t datum_size = 0;
642              if (!copyToByteString(datum_size, bs)) return;
643 
644              // copy data
645              if (!copyToByteString(*ptr, bs)) return;
646 
647              // save correct size
648              const size_t diff = bs.size() - idx - sizeof(datum_size);
649              if (diff > std::numeric_limits<datum_size_t>::max()) return;
650              datum_size = diff;
651              std::copy((uint8_t*)&datum_size, (uint8_t*)&datum_size + sizeof(datum_size),
652                        bs.begin() + idx);
653              success = true;
654          }, &datum) && success;
655 }
656 
657 /**
658  * Obtaining the Datum back from ByteString
659  */
660 
661 // A container that lists all the unknown types found during parsing.
662 using ByteStringUnknowns = std::vector<type_size_t>;
663 
664 // forward decl for recursion - do not remove.
665 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t& idx,
666         ByteStringUnknowns *unknowns);
667 
668 template <template <typename ...> class V, typename... Args>
669 bool copyFromByteString(V<Args...> *v, const ByteString& bs, size_t& idx,
670         ByteStringUnknowns *unknowns);
671 
672 // primitive
673 template <typename T>
674 std::enable_if_t<
675         is_primitive_metadata_type_v<T> ||
676         std::is_arithmetic_v<std::decay_t<T>>,
677         bool
678         >
copyFromByteString(T * dest,const ByteString & bs,size_t & idx,ByteStringUnknowns * unknowns)679 copyFromByteString(T *dest, const ByteString& bs, size_t& idx,
680         ByteStringUnknowns *unknowns __attribute__((unused))) {
681     if (idx + sizeof(T) > bs.size()) return false;
682     std::copy(bs.begin() + idx, bs.begin() + idx + sizeof(T), (uint8_t*)dest);
683     idx += sizeof(T);
684     return true;
685 }
686 
687 // pairs
688 template <typename A, typename B>
copyFromByteString(std::pair<A,B> * p,const ByteString & bs,size_t & idx,ByteStringUnknowns * unknowns)689 bool copyFromByteString(std::pair<A, B>* p, const ByteString& bs, size_t& idx,
690         ByteStringUnknowns *unknowns) {
691     return copyFromByteString(&p->first, bs, idx, unknowns)
692             && copyFromByteString(&p->second, bs, idx, unknowns);
693 }
694 
695 // containers
696 template <template <typename ...> class V, typename... Args>
copyFromByteString(V<Args...> * v,const ByteString & bs,size_t & idx,ByteStringUnknowns * unknowns)697 bool copyFromByteString(V<Args...> *v, const ByteString& bs, size_t& idx,
698         ByteStringUnknowns *unknowns) {
699     index_size_t size;
700     if (!copyFromByteString(&size, bs, idx, unknowns)) return false;
701 
702     if constexpr (std::is_same_v<std::decay_t<V<Args...>>, std::string>) {
703         if (size > bs.size() - idx) return false;
704         v->resize(size);
705         for (index_size_t i = 0; i < size; ++i) {
706             (*v)[i] = bs[idx++];
707         }
708     } else if constexpr (is_specialization_v<std::decay_t<V<Args...>>, std::vector>) {
709         for (index_size_t i = 0; i < size; ++i) {
710             std::decay_t<decltype(*v->begin())> value{};
711             if (!copyFromByteString(&value, bs, idx, unknowns)) {
712                 return false;
713             }
714             if constexpr (std::is_same_v<std::decay_t<decltype(value)>, Datum>) {
715                 if (!value.has_value()) {
716                     continue;  // ignore empty datum values in a vector.
717                 }
718             }
719             v->emplace_back(std::move(value));
720         }
721     } else if constexpr (is_specialization_v<std::decay_t<V<Args...>>, std::map>) {
722         for (index_size_t i = 0; i < size; ++i) {
723             // we can't directly use pair because there may be internal const decls.
724             std::decay_t<decltype(v->begin()->first)> key{};
725             std::decay_t<decltype(v->begin()->second)> value{};
726             if (!copyFromByteString(&key, bs, idx, unknowns) ||
727                     !copyFromByteString(&value, bs, idx, unknowns)) {
728                 return false;
729             }
730             if constexpr (std::is_same_v<std::decay_t<decltype(value)>, Datum>) {
731                 if (!value.has_value()) {
732                     continue;  // ignore empty datum values in a map.
733                 }
734             }
735             v->emplace(std::move(key), std::move(value));
736         }
737     } else /* constexpr */ {
738         for (index_size_t i = 0; i < size; ++i) {
739             std::decay_t<decltype(*v->begin())> value{};
740             if (!copyFromByteString(&value, bs, idx, unknowns)) {
741                 return false;
742             }
743             v->emplace(std::move(value));
744         }
745     }
746     return true;
747 }
748 
749 // simple structs (use structured binding to extract members)
750 template <typename T>
751 typename std::enable_if_t<is_structural_metadata_type_v<T>, bool>
copyFromByteString(T * t,const ByteString & bs,size_t & idx,ByteStringUnknowns * unknowns)752 copyFromByteString(T *t, const ByteString& bs, size_t& idx,
753         ByteStringUnknowns *unknowns) {
754     using type = std::decay_t<T>;
755     if constexpr (is_braces_constructible<type, any_type, any_type, any_type, any_type>{}) {
756         auto& [e1, e2, e3, e4] =  *t;
757         return copyFromByteString(&e1, bs, idx, unknowns)
758             && copyFromByteString(&e2, bs, idx, unknowns)
759             && copyFromByteString(&e3, bs, idx, unknowns)
760             && copyFromByteString(&e4, bs, idx, unknowns);
761     } else if constexpr (is_braces_constructible<type, any_type, any_type, any_type>{}) {
762         auto& [e1, e2, e3] =  *t;
763         return copyFromByteString(&e1, bs, idx, unknowns)
764             && copyFromByteString(&e2, bs, idx, unknowns)
765             && copyFromByteString(&e3, bs, idx, unknowns);
766     } else if constexpr (is_braces_constructible<type, any_type, any_type>{}) {
767         auto& [e1, e2] =  *t;
768         return copyFromByteString(&e1, bs, idx, unknowns)
769             && copyFromByteString(&e2, bs, idx, unknowns);
770     } else if constexpr (is_braces_constructible<type, any_type>{}) {
771         auto& [e1] =  *t;
772         return copyFromByteString(&e1, bs, idx, unknowns);
773     } else if constexpr (is_braces_constructible<type>{}) {
774         return true; // like std::monostate - no members
775     } else /* constexpr */ {
776         static_assert(dependent_false_v<T>);
777     }
778 }
779 
780 namespace tedious_details {
781 //
782 // We build a function table at compile time to lookup the proper copyFromByteString method.
783 // See:
784 // https://stackoverflow.com/questions/36785345/void-to-the-nth-element-of-stdtuple-at-runtime
785 // Constant time implementation of std::visit (variant)
786 
787 template <typename CompoundT, size_t Index>
copyFromByteString(Datum * datum,const ByteString & bs,size_t & idx,size_t endIdx,ByteStringUnknowns * unknowns)788 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t &idx, size_t endIdx,
789         ByteStringUnknowns *unknowns) {
790    using T = std::tuple_element_t<Index, typename CompoundT::tuple_t>;
791    T value;
792    if (!android::audio_utils::metadata::copyFromByteString(
793            &value, bs, idx, unknowns)) return false;  // have we parsed correctly?
794    if (idx != endIdx) return false;  // have we consumed the correct number of bytes?
795    *datum = std::move(value);
796    return true;
797 }
798 
799 template <typename CompoundT, size_t... Indexes>
copyFromByteString(Datum * datum,const ByteString & bs,size_t & idx,size_t endIdx,ByteStringUnknowns * unknowns,size_t typeIndex,std::index_sequence<Indexes...>)800 constexpr bool copyFromByteString(Datum *datum, const ByteString &bs,
801         size_t &idx, size_t endIdx, ByteStringUnknowns *unknowns,
802         size_t typeIndex, std::index_sequence<Indexes...>)
803 {
804     using function_type =
805             bool (*)(Datum*, const ByteString&, size_t&, size_t, ByteStringUnknowns*);
806     function_type constexpr ptrs[] = {
807         &copyFromByteString<CompoundT, Indexes>...
808     };
809     return ptrs[typeIndex](datum, bs, idx, endIdx, unknowns);
810 }
811 
812 template <typename CompoundT>
813 __attribute__((noinline))
copyFromByteString(Datum * datum,const ByteString & bs,size_t & idx,size_t endIdx,ByteStringUnknowns * unknowns,size_t typeIndex)814 constexpr bool copyFromByteString(Datum *datum, const ByteString &bs,
815         size_t &idx, size_t endIdx, ByteStringUnknowns *unknowns, size_t typeIndex) {
816   return copyFromByteString<CompoundT>(
817           datum, bs, idx, endIdx, unknowns,
818           typeIndex, std::make_index_sequence<CompoundT::size_v>());
819 }
820 
821 } // namespace tedious_details
822 
823 // TODO Ditto about moving to .cpp.
824 
825 inline
copyFromByteString(Datum * datum,const ByteString & bs,size_t & idx,ByteStringUnknowns * unknowns)826 bool copyFromByteString(Datum *datum, const ByteString &bs, size_t& idx,
827         ByteStringUnknowns *unknowns) {
828     type_size_t type;
829     if (!copyFromByteString(&type, bs, idx, unknowns)) return false;
830 
831     datum_size_t datum_size;
832     if (!copyFromByteString(&datum_size, bs, idx, unknowns)) return false;
833     if (datum_size > bs.size() - idx) return false;
834     const size_t endIdx = idx + datum_size;
835 
836     if (type == 0 || type > metadata_types::size_v) {
837         idx = endIdx; // skip unrecognized type.
838         if (unknowns != nullptr) {
839             unknowns->push_back(type);
840             return true;  // allow further recursion.
841         }
842         return false;
843     }
844 
845     // use special trick to instantiate all the types for copyFromByteString
846     // in a table and find the right method from table lookup.
847     return tedious_details::copyFromByteString<metadata_types>(
848             datum, bs, idx, endIdx, unknowns, type - 1);
849 }
850 
851 // Handy helpers - these are the most efficient ways to parcel Data.
852 /**
853  * Returns the Data map from a byte string.
854  *
855  * If unknowns is nullptr, then any unknown entries during parsing will cause
856  * an empty map to be returned.
857  *
858  * If unknowns is non-null, then it contains all of the unknown types
859  * encountered during parsing, and a partial map will be returned excluding all
860  * unknown types encountered.
861  */
862 inline
863 Data dataFromByteString(const ByteString &bs,
864         ByteStringUnknowns *unknowns = nullptr) {
865     Data d;
866     size_t idx = 0;
867     if (!copyFromByteString(&d, bs, idx, unknowns)) {
868         return {};
869     }
870     return d; // copy elision
871 }
872 
873 inline
byteStringFromData(const Data & data)874 ByteString byteStringFromData(const Data &data) {
875     ByteString bs;
876     copyToByteString(data, bs);
877     return bs; // copy elision
878 }
879 
880 /**
881  * \brief Returns the length of the byte string buffer from the raw pointer.
882  *
883  * The raw pointer comes from the Data object's ByteString.data()
884  * or from the C API byte_string_from_audio_metadata().
885  * This is a helper method for C implementations which may pass the raw
886  * byte string buffer pointer (which does not directly contain the length).
887  * C++ methods should always use the ByteString object.
888  *
889  * \param byteString       byte string buffer raw pointer.
890  * \return size in bytes of metadata in the buffer or 0 if something went wrong.
891  */
892 
dataByteStringLen(const uint8_t * ptr)893 inline size_t dataByteStringLen(const uint8_t *ptr) {
894     index_size_t elements;
895     const uint8_t * const origPtr = ptr;
896     memcpy(&elements, ptr, sizeof(elements));
897     ptr += sizeof(elements);
898     for (index_size_t i = 0; i < elements; ++i) {
899         // get key (string)
900         index_size_t keyLen;
901         memcpy(&keyLen, ptr, sizeof(keyLen));
902         ptr += keyLen + sizeof(keyLen);
903         // get type
904         type_size_t type;
905         memcpy(&type, ptr, sizeof(type));
906         ptr += sizeof(type_size_t);
907         // Note: could check type validity.
908         // payload size
909         datum_size_t datumSize;
910         memcpy(&datumSize, ptr, sizeof(datumSize));
911         ptr += datumSize + sizeof(datumSize);
912     }
913     const ptrdiff_t size = ptr - origPtr;
914     return size < 0 ? 0 : size;
915 }
916 
917 } // namespace android::audio_utils::metadata
918 
919 #endif // __cplusplus
920 
921 // C API (see C++ API above for details)
922 
923 /** \cond */
924 __BEGIN_DECLS
925 /** \endcond */
926 
927 typedef struct audio_metadata_t audio_metadata_t;
928 
929 // Used by audio_metadata_put_unknown() and audio_metadata_get_unknown(), but not part of public API
930 // The name and data structure representation discourage accidental use.
931 typedef struct { char c; } audio_metadata_unknown_t;
932 
933 /**
934  * \brief Creates a metadata object
935  *
936  * \return the metadata object or NULL on failure. Caller must call
937  *         audio_metadata_destroy to free memory.
938  */
939 audio_metadata_t *audio_metadata_create();
940 
941 /**
942  * \brief Put key value pair where the value type is int32_t to audio metadata.
943  *
944  * \param metadata         the audio metadata object.
945  * \param key              the key of the element to be put.
946  * \param value            the value of the element to be put.
947  * \return 0 if the key value pair is put successfully into the audio metadata.
948  *         -EINVAL if metadata or key is null.
949  */
950 int audio_metadata_put_int32(audio_metadata_t *metadata, const char *key, int32_t value);
951 
952 /**
953  * \brief Put key value pair where the value type is int64_t to audio metadata.
954  *
955  * \param metadata         the audio metadata object.
956  * \param key              the key of the element to be put.
957  * \param value            the value of the element to be put.
958  * \return 0 if the key value pair is put successfully into the audio metadata.
959  *         -EINVAL if metadata or key is null.
960  */
961 int audio_metadata_put_int64(audio_metadata_t *metadata, const char *key, int64_t value);
962 
963 /**
964  * \brief Put key value pair where the value type is float to audio metadata.
965  *
966  * \param metadata         the audio metadata object.
967  * \param key              the key of the element to be put.
968  * \param value            the value of the element to be put.
969  * \return 0 if the key value pair is put successfully into the audio metadata.
970  *         -EINVAL if metadata or key is null.
971  */
972 int audio_metadata_put_float(audio_metadata_t *metadata, const char *key, float value);
973 
974 /**
975  * \brief Put key value pair where the value type is double to audio metadata.
976  *
977  * \param metadata         the audio metadata object.
978  * \param key              the key of the element to be put.
979  * \param value            the value of the element to be put.
980  * \return 0 if the key value pair is put successfully into the audio metadata.
981  *         -EINVAL if metadata or key is null.
982  */
983 int audio_metadata_put_double(audio_metadata_t *metadata, const char *key, double value);
984 
985 /**
986  * \brief Put key value pair where the value type is `const char *` to audio metadata.
987  *
988  * \param metadata         the audio metadata object.
989  * \param key              the key of the element to be put.
990  * \param value            the value of the element to be put.
991  * \return 0 if the key value pair is put successfully into the audio metadata.
992  *         -EINVAL if metadata, key or value is null.
993  */
994 int audio_metadata_put_string(audio_metadata_t *metadata, const char *key, const char *value);
995 
996 /**
997  * \brief Put key value pair where the value type is audio_metadata_t to audio metadata.
998  *
999  * \param metadata         the audio metadata object.
1000  * \param key              the key of the element to be put.
1001  * \param value            the value of the element to be put.
1002  * \return 0 if the key value pair is put successfully into the audio metadata.
1003  *         -EINVAL if metadata, key or value is null.
1004  */
1005 int audio_metadata_put_data(audio_metadata_t *metadata, const char *key, audio_metadata_t *value);
1006 
1007 /**
1008  * \brief Declared but not implemented, as any potential caller won't supply a correct value.
1009  */
1010 int audio_metadata_put_unknown(audio_metadata_t *metadata, const char *key,
1011         audio_metadata_unknown_t value);
1012 
1013 #ifndef __cplusplus // Only C11 has _Generic; C++ uses overloaded declarations instead
1014 
1015 // use C Generics to provide interfaces for put/get functions
1016 // See: https://en.cppreference.com/w/c/language/generic
1017 
1018 /**
1019  * A generic interface to put key value pair into the audio metadata.
1020  * Fails at compile-time if type isn't supported.
1021  */
1022 #define audio_metadata_put(metadata, key, value) _Generic((value), \
1023     int32_t: audio_metadata_put_int32,                             \
1024     int64_t: audio_metadata_put_int64,                             \
1025     float: audio_metadata_put_float,                               \
1026     double: audio_metadata_put_double,                             \
1027     /* https://stackoverflow.com/questions/18857056/c11-generic-how-to-deal-with-string-literals */ \
1028     const char*: audio_metadata_put_string,                        \
1029     char*: audio_metadata_put_string,                              \
1030     audio_metadata_t*: audio_metadata_put_data,                    \
1031     default: audio_metadata_put_unknown                            \
1032     )(metadata, key, value)
1033 
1034 #endif  // !__cplusplus
1035 
1036 /**
1037  * \brief Get mapped value whose type is int32_t by a given key from audio metadata.
1038  *
1039  * \param metadata         the audio metadata object.
1040  * \param key              the key value to get value.
1041  * \param value            the mapped value to be written.
1042  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1043  *         -ENOENT when 1) key is found in the audio metadata,
1044  *                      2) the type of mapped value is not int32_t.
1045  *         0 if successfully find the mapped value.
1046  */
1047 int audio_metadata_get_int32(audio_metadata_t *metadata, const char *key, int32_t *value);
1048 
1049 /**
1050  * \brief Get mapped value whose type is int64_t by a given key from audio metadata.
1051  *
1052  * \param metadata         the audio metadata object.
1053  * \param key              the key value to get value.
1054  * \param value            the mapped value to be written.
1055  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1056  *         -ENOENT when 1) key is found in the audio metadata,
1057  *                      2) the type of mapped value is not int32_t.
1058  *         0 if successfully find the mapped value.
1059  */
1060 int audio_metadata_get_int64(audio_metadata_t *metadata, const char *key, int64_t *value);
1061 
1062 /**
1063  * \brief Get mapped value whose type is float by a given key from audio metadata.
1064  *
1065  * \param metadata         the audio metadata object.
1066  * \param key              the key value to get value.
1067  * \param value            the mapped value to be written.
1068  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1069  *         -ENOENT when 1) key is found in the audio metadata,
1070  *                      2) the type of mapped value is not float.
1071  *         0 if successfully find the mapped value.
1072  */
1073 int audio_metadata_get_float(audio_metadata_t *metadata, const char *key, float *value);
1074 
1075 /**
1076  * \brief Get mapped value whose type is double by a given key from audio metadata.
1077  *
1078  * \param metadata         the audio metadata object.
1079  * \param key              the key value to get value.
1080  * \param value            the mapped value to be written.
1081  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1082  *         -ENOENT when 1) key is found in the audio metadata,
1083  *                      2) the type of mapped value is not double.
1084  *         0 if successfully find the mapped value.
1085  */
1086 int audio_metadata_get_double(audio_metadata_t *metadata, const char *key, double *value);
1087 
1088 /**
1089  * \brief Get mapped value whose type is std::string by a given key from audio metadata.
1090  *
1091  * \param metadata         the audio metadata object.
1092  * \param key              the key value to get value.
1093  * \param value            the mapped value to be written. The memory will be allocated in the
1094  *                         function, which must be freed by caller.
1095  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1096  *         -ENOENT when 1) key is found in the audio metadata,
1097  *                      2) the type of mapped value is not std::string.
1098  *         -ENOMEM when fails allocating memory for value.
1099  *         0 if successfully find the mapped value.
1100  */
1101 int audio_metadata_get_string(audio_metadata_t *metadata, const char *key, char **value);
1102 
1103 /**
1104  * \brief Get mapped value whose type is audio_metadata_t by a given key from audio metadata.
1105  *
1106  * \param metadata         the audio metadata object.
1107  * \param key              the key value to get value.
1108  * \param value            the mapped value to be written. The memory will be allocated in the
1109  *                         function, which should be free by caller via audio_metadata_destroy.
1110  * \return -EINVAL when 1) metadata is null, 2) key is null, or 3) value is null.
1111  *         -ENOENT when 1) key is found in the audio metadata,
1112  *                      2) the type of mapped value is not audio_utils::metadata::Data.
1113  *         -ENOMEM when fails allocating memory for value.
1114  *         0 if successfully find the mapped value.
1115  */
1116 int audio_metadata_get_data(audio_metadata_t *metadata, const char *key, audio_metadata_t **value);
1117 
1118 /**
1119  * \brief Declared but not implemented, as any potential caller won't supply a correct value.
1120  */
1121 int audio_metadata_get_unknown(audio_metadata_t *metadata, const char *key,
1122         audio_metadata_unknown_t *value);
1123 
1124 #ifndef __cplusplus // Only C11 has _Generic; C++ uses overloaded declarations instead
1125 
1126 /**
1127  * A generic interface to get mapped value by a given key from audio metadata. The value object
1128  * will remain the same if the key is not found in the audio metadata.
1129  * Fails at compile-time if type isn't supported.
1130  */
1131 #define audio_metadata_get(metadata, key, value) _Generic((value), \
1132     int32_t*: audio_metadata_get_int32,                            \
1133     int64_t*: audio_metadata_get_int64,                            \
1134     float*: audio_metadata_get_float,                              \
1135     double*: audio_metadata_get_double,                            \
1136     char**: audio_metadata_get_string,                             \
1137     audio_metadata_t**: audio_metadata_get_data,                   \
1138     default: audio_metadata_get_unknown                            \
1139     )(metadata, key, value)
1140 
1141 #endif  // !__cplusplus
1142 
1143 /**
1144  * \brief Remove item from audio metadata.
1145  *
1146  * \param metadata         the audio metadata object.
1147  * \param key              the key of the item that is going to be removed.
1148  * \return -EINVAL if metadata or key is null. Otherwise, return the number of elements erased.
1149  */
1150 ssize_t audio_metadata_erase(audio_metadata_t *metadata, const char *key);
1151 
1152 /**
1153  * \brief Destroys the metadata object
1154  *
1155  * \param metadata         object returned by create, if NULL nothing happens.
1156  */
1157 void audio_metadata_destroy(audio_metadata_t *metadata);
1158 
1159 /**
1160  * \brief Unpack byte string into a given audio metadata
1161  *
1162  * \param byteString       a byte string that contains data to convert to audio metadata.
1163  * \param length           the length of the byte string
1164  * \return the audio metadata object that contains the converted data. Caller must call
1165  *         audio_metadata_destroy to free the memory.
1166  */
1167 audio_metadata_t *audio_metadata_from_byte_string(const uint8_t *byteString, size_t length);
1168 
1169 /**
1170  * \brief Pack the audio metadata into a byte string
1171  *
1172  * \param metadata         the audio metadata object to be converted.
1173  * \param byteString       the buffer to write data to. The memory will be allocated
1174  *                         in the function, which must be freed by caller via free().
1175  * \return -EINVAL if metadata or byteString is null.
1176  *         -ENOMEM if fails to allocate memory for byte string.
1177  *         The length of the byte string.
1178  */
1179 ssize_t byte_string_from_audio_metadata(audio_metadata_t *metadata, uint8_t **byteString);
1180 
1181 /**
1182  * \brief Return the size in bytes of the metadata byte string
1183  *
1184  * Note: strlen() cannot be used as there are embedded 0's in the byte string.
1185  *
1186  * \param byteString       a valid byte string buffer from byte_string_from_audio_metadata().
1187  * \return size in bytes of metadata in the buffer or 0 if something went wrong.
1188  */
1189 size_t audio_metadata_byte_string_len(const uint8_t *byteString);
1190 
1191 /** \cond */
1192 __END_DECLS
1193 /** \endcond */
1194 
1195 #ifdef __cplusplus
1196 
1197 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,int32_t value)1198 int audio_metadata_put(audio_metadata_t *metadata, const char *key, int32_t value)
1199 {
1200     return audio_metadata_put_int32(metadata, key, value);
1201 }
1202 
1203 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,int64_t value)1204 int audio_metadata_put(audio_metadata_t *metadata, const char *key, int64_t value)
1205 {
1206     return audio_metadata_put_int64(metadata, key, value);
1207 }
1208 
1209 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,float value)1210 int audio_metadata_put(audio_metadata_t *metadata, const char *key, float value)
1211 {
1212     return audio_metadata_put_float(metadata, key, value);
1213 }
1214 
1215 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,double value)1216 int audio_metadata_put(audio_metadata_t *metadata, const char *key, double value)
1217 {
1218     return audio_metadata_put_double(metadata, key, value);
1219 }
1220 
1221 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,const char * value)1222 int audio_metadata_put(audio_metadata_t *metadata, const char *key, const char *value)
1223 {
1224     return audio_metadata_put_string(metadata, key, value);
1225 }
1226 
1227 inline
audio_metadata_put(audio_metadata_t * metadata,const char * key,audio_metadata_t * value)1228 int audio_metadata_put(audio_metadata_t *metadata, const char *key, audio_metadata_t *value)
1229 {
1230     return audio_metadata_put_data(metadata, key, value);
1231 }
1232 
1233 // No overload for default type
1234 
1235 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,int32_t * value)1236 int audio_metadata_get(audio_metadata_t *metadata, const char *key, int32_t *value)
1237 {
1238     return audio_metadata_get_int32(metadata, key, value);
1239 }
1240 
1241 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,int64_t * value)1242 int audio_metadata_get(audio_metadata_t *metadata, const char *key, int64_t *value)
1243 {
1244     return audio_metadata_get_int64(metadata, key, value);
1245 }
1246 
1247 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,float * value)1248 int audio_metadata_get(audio_metadata_t *metadata, const char *key, float *value)
1249 {
1250     return audio_metadata_get_float(metadata, key, value);
1251 }
1252 
1253 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,double * value)1254 int audio_metadata_get(audio_metadata_t *metadata, const char *key, double *value)
1255 {
1256     return audio_metadata_get_double(metadata, key, value);
1257 }
1258 
1259 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,char ** value)1260 int audio_metadata_get(audio_metadata_t *metadata, const char *key, char **value)
1261 {
1262     return audio_metadata_get_string(metadata, key, value);
1263 }
1264 
1265 inline
audio_metadata_get(audio_metadata_t * metadata,const char * key,audio_metadata_t ** value)1266 int audio_metadata_get(audio_metadata_t *metadata, const char *key, audio_metadata_t **value)
1267 {
1268     return audio_metadata_get_data(metadata, key, value);
1269 }
1270 
1271 // No overload for default type
1272 
1273 #endif  // __cplusplus
1274 
1275 #endif // !ANDROID_AUDIO_METADATA_H
1276