1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMMON_NAPI_H
17 #define COMMON_NAPI_H
18 
19 #include <map>
20 #include <string>
21 #include <vector>
22 #include <unordered_map>
23 #include "meta/format.h"
24 #include "meta/meta.h"
25 #include "av_common.h"
26 #include "napi/native_api.h"
27 #include "napi/native_node_api.h"
28 #include "media_core.h"
29 #include "audio_info.h"
30 #include "audio_system_manager.h"
31 
32 namespace OHOS {
33 namespace Media {
34 struct AVFileDescriptor;
35 struct AVPlayStrategyTmp;
36 struct AVDataSrcDescriptor;
37 class AVMediaSourceTmp;
38 /**
39  * customInfo max count
40 */
41 constexpr uint32_t MAX_COUNT = 500;
42 /**
43  * NOTE: use on AVRecorderConfig.metadata.customInfo
44 */
45 constexpr uint32_t CUSTOM_MAX_LENGTH = 1001;
46 class CommonNapi {
47 public:
48     CommonNapi() = delete;
49     ~CommonNapi() = delete;
50     static std::string GetStringArgument(napi_env env, napi_value value, size_t maxLength = PATH_MAX);
51     static bool CheckValueType(napi_env env, napi_value arg, napi_valuetype type);
52     static bool CheckhasNamedProperty(napi_env env, napi_value arg, std::string type);
53     static bool GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result);
54     static bool GetPropertyUint32(napi_env env, napi_value configObj, const std::string &type, uint32_t &result);
55     static bool GetPropertyInt64(napi_env env, napi_value configObj, const std::string &type, int64_t &result);
56     static bool GetPropertyDouble(napi_env env, napi_value configObj, const std::string &type, double &result);
57     static std::string GetPropertyString(napi_env env, napi_value configObj, const std::string &type);
58     // support Record<string, string>
59     static napi_status GetPropertyRecord(napi_env env, napi_value in, Meta &meta, std::string type);
60     static bool GetPropertyMap(napi_env env, napi_value value, std::map<std::string, std::string>& map);
61     static bool GetFdArgument(napi_env env, napi_value value, AVFileDescriptor &rawFd);
62     static bool GetPlayStrategy(napi_env env, napi_value value, AVPlayStrategyTmp &playStrategy);
63     static napi_status FillErrorArgs(napi_env env, int32_t errCode, const napi_value &args);
64     static napi_status CreateError(napi_env env, int32_t errCode, const std::string &errMsg, napi_value &errVal);
65     static napi_ref CreateReference(napi_env env, napi_value arg);
66     static napi_deferred CreatePromise(napi_env env, napi_ref ref, napi_value &result);
67     static bool SetPropertyByValueType(napi_env env, napi_value &obj, std::shared_ptr<Meta> &meta, std::string key);
68     static bool SetPropertyInt32(napi_env env, napi_value &obj, const std::string &key, int32_t value);
69     static bool SetPropertyInt64(napi_env env, napi_value &obj, const std::string &key, int64_t value);
70     static bool SetPropertyDouble(napi_env env, napi_value &obj, const std::string &key, double value);
71     static bool SetPropertyBool(napi_env env, napi_value &obj, const std::string &key, bool value);
72     static bool SetPropertyString(napi_env env, napi_value &obj, const std::string &key, const std::string &value);
73     static napi_value CreateFormatBuffer(napi_env env, Format &format);
74     static bool CreateFormatBufferByRef(napi_env env, Format &format, napi_value &result);
75     static bool AddRangeProperty(napi_env env, napi_value obj, const std::string &name, int32_t min, int32_t max);
76     static bool AddArrayProperty(napi_env env, napi_value obj, const std::string &name,
77         const std::vector<int32_t> &vec);
78     static bool AddNumberPropInt32(napi_env env, napi_value obj, const std::string &key, int32_t value);
79     static bool AddNumberPropInt64(napi_env env, napi_value obj, const std::string &key, int64_t value);
80     static bool AddArrayInt(napi_env env, napi_value &array, const std::vector<int32_t> &vec);
81     static bool AddStringProperty(napi_env env, napi_value obj, const std::string &key, const std::string &value);
82     static bool GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result);
83 
84     static void ConvertDeviceInfoToAudioDeviceDescriptor(
85         sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor, const AudioStandard::DeviceInfo &deviceInfo);
86     static napi_status SetValueDeviceInfo(const napi_env &env, const AudioStandard::DeviceInfo &deviceInfo,
87         napi_value &result);
88     static napi_status SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
89         napi_value &result);
90     static napi_status SetDeviceDescriptors(const napi_env &env,
91         const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors, napi_value &result);
92 };
93 
94 class MediaJsResult {
95 public:
96     virtual ~MediaJsResult() = default;
97     virtual napi_status GetJsResult(napi_env env, napi_value &result) = 0;
98 };
99 
100 class MediaJsResultBoolean : public MediaJsResult {
101 public:
MediaJsResultBoolean(bool value)102     explicit MediaJsResultBoolean(bool value)
103         : value_(value)
104     {
105     }
106     ~MediaJsResultBoolean() = default;
GetJsResult(napi_env env,napi_value & result)107     napi_status GetJsResult(napi_env env, napi_value &result) override
108     {
109         return napi_get_boolean(env, value_, &result);
110     }
111 private:
112     bool value_;
113 };
114 
115 class MediaJsResultInt : public MediaJsResult {
116 public:
MediaJsResultInt(int32_t value)117     explicit MediaJsResultInt(int32_t value)
118         : value_(value)
119     {
120     }
121     ~MediaJsResultInt() = default;
GetJsResult(napi_env env,napi_value & result)122     napi_status GetJsResult(napi_env env, napi_value &result) override
123     {
124         return napi_create_int32(env, value_, &result);
125     }
126 private:
127     int32_t value_;
128 };
129 
130 class MediaJsResultString : public MediaJsResult {
131 public:
MediaJsResultString(const std::string & value)132     explicit MediaJsResultString(const std::string &value)
133         : value_(value)
134     {
135     }
136     ~MediaJsResultString() = default;
GetJsResult(napi_env env,napi_value & result)137     napi_status GetJsResult(napi_env env, napi_value &result) override
138     {
139         return napi_create_string_utf8(env, value_.c_str(), NAPI_AUTO_LENGTH, &result);
140     }
141 
142 private:
143     std::string value_;
144 };
145 
146 class MediaJsResultStringVector : public MediaJsResult {
147 public:
MediaJsResultStringVector(const std::vector<std::string> & value)148     explicit MediaJsResultStringVector(const std::vector<std::string> &value)
149         : value_(value)
150     {
151     }
152     ~MediaJsResultStringVector() = default;
153     napi_status GetJsResult(napi_env env, napi_value &result) override;
154 
155 private:
156     std::vector<std::string> value_;
157 };
158 
159 class MediaJsResultIntArray : public MediaJsResult {
160 public:
MediaJsResultIntArray(const std::vector<int32_t> & value)161     explicit MediaJsResultIntArray(const std::vector<int32_t> &value)
162         : value_(value)
163     {
164     }
165     ~MediaJsResultIntArray() = default;
166     napi_status GetJsResult(napi_env env, napi_value &result) override;
167 
168 private:
169     std::vector<int32_t> value_;
170 };
171 
172 class MediaJsResultArray : public MediaJsResult {
173 public:
MediaJsResultArray(const std::vector<Format> & value)174     explicit MediaJsResultArray(const std::vector<Format> &value)
175         : value_(value)
176     {
177     }
178     ~MediaJsResultArray() = default;
179     napi_status GetJsResult(napi_env env, napi_value &result) override;
180 
181 private:
182     std::vector<Format> value_;
183 };
184 
185 class MediaJsResultRange : public MediaJsResult {
186 public:
MediaJsResultRange(int32_t min,int32_t max)187     explicit MediaJsResultRange(int32_t min, int32_t max)
188         : min_(min),
189           max_(max)
190     {
191     }
192     ~MediaJsResultRange() = default;
GetJsResult(napi_env env,napi_value & result)193     napi_status GetJsResult(napi_env env, napi_value &result) override
194     {
195         napi_status status = napi_create_object(env, &result);
196         if (status != napi_ok) {
197             return status;
198         }
199 
200         if (!CommonNapi::SetPropertyInt32(env, result, "min", min_)) {
201             return napi_invalid_arg;
202         }
203 
204         if (!CommonNapi::SetPropertyInt32(env, result, "max", max_)) {
205             return napi_invalid_arg;
206         }
207 
208         return napi_ok;
209     }
210 private:
211     int32_t min_;
212     int32_t max_;
213 };
214 
215 class MediaJsResultInstance : public MediaJsResult {
216 public:
MediaJsResultInstance(const napi_ref & constructor)217     explicit MediaJsResultInstance(const napi_ref &constructor)
218         : constructor_(constructor)
219     {
220     }
221     ~MediaJsResultInstance() = default;
GetJsResult(napi_env env,napi_value & result)222     napi_status GetJsResult(napi_env env, napi_value &result) override
223     {
224         napi_value constructor = nullptr;
225         napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
226         if (ret != napi_ok || constructor == nullptr) {
227             return ret;
228         }
229         return napi_new_instance(env, constructor, 0, nullptr, &result);
230     }
231 
232 private:
233     napi_ref constructor_;
234 };
235 
236 class AVCodecJsResultCtor : public MediaJsResult {
237 public:
AVCodecJsResultCtor(const napi_ref & constructor,int32_t isMimeType,const std::string & name)238     AVCodecJsResultCtor(const napi_ref &constructor, int32_t isMimeType, const std::string &name)
239         : constructor_(constructor),
240           isMimeType_(isMimeType),
241           name_(name)
242     {
243     }
244     ~AVCodecJsResultCtor() = default;
GetJsResult(napi_env env,napi_value & result)245     napi_status GetJsResult(napi_env env, napi_value &result) override
246     {
247         napi_value constructor = nullptr;
248         napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
249         if (ret != napi_ok || constructor == nullptr) {
250             return ret;
251         }
252 
253         napi_value args[2] = { nullptr };
254         ret = napi_create_string_utf8(env, name_.c_str(), NAPI_AUTO_LENGTH, &args[0]);
255         if (ret != napi_ok) {
256             return ret;
257         }
258 
259         ret = napi_create_int32(env, isMimeType_, &args[1]);
260         if (ret != napi_ok) {
261             return ret;
262         }
263 
264         return napi_new_instance(env, constructor, 2, args, &result); // The number of parameters is 2
265     }
266 
267 private:
268     napi_ref constructor_;
269     int32_t isMimeType_ = 0;
270     std::string name_ = "";
271 };
272 
273 class AVCodecJsResultFormat : public MediaJsResult {
274 public:
AVCodecJsResultFormat(const Format & format)275     explicit AVCodecJsResultFormat(const Format &format)
276         : format_(format)
277     {
278     }
279     ~AVCodecJsResultFormat() = default;
GetJsResult(napi_env env,napi_value & result)280     napi_status GetJsResult(napi_env env, napi_value &result) override
281     {
282         (void)CommonNapi::CreateFormatBufferByRef(env, format_, result);
283         return napi_ok;
284     }
285 
286 private:
287     Format format_;
288 };
289 
290 struct MediaAsyncContext {
291     explicit MediaAsyncContext(napi_env env);
292     virtual ~MediaAsyncContext();
293     static void CompleteCallback(napi_env env, napi_status status, void *data);
294     static void Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args);
295     static void CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args);
296     void SignError(int32_t code, const std::string &message, bool del = true);
297     std::string memoryTagHead = "safe";
298     napi_env env_;
299     napi_async_work work = nullptr;
300     napi_deferred deferred = nullptr;
301     napi_ref callbackRef = nullptr;
302     std::unique_ptr<MediaJsResult> JsResult;
303     bool errFlag = false;
304     int32_t errCode = 0;
305     std::string errMessage = "";
306     bool delFlag = true;
307     bool ctorFlag = false;
308     std::string memoryTagTail = "memory";
309 };
310 
311 struct AutoRef {
AutoRefAutoRef312     AutoRef(napi_env env, napi_ref cb)
313         : env_(env), cb_(cb)
314     {
315     }
~AutoRefAutoRef316     ~AutoRef()
317     {
318         if (env_ != nullptr && cb_ != nullptr) {
319             (void)napi_delete_reference(env_, cb_);
320         }
321     }
322     napi_env env_;
323     napi_ref cb_;
324 };
325 
326 struct AVDataSrcDescriptor {
327     int64_t fileSize = 0;
328     napi_value callback = nullptr;
329 };
330 
331 class AVMediaSourceTmp {
332 public:
333     AVMediaSourceTmp() = default;
~AVMediaSourceTmp()334     ~AVMediaSourceTmp()
335     {
336         header.clear();
337     }
338 
SetMimeType(const std::string & mimeType)339     void SetMimeType(const std::string& mimeType)
340     {
341         mimeType_ = mimeType;
342     }
343 
GetMimeType()344     std::string GetMimeType() const
345     {
346         return mimeType_;
347     }
348 
349     std::map<std::string, std::string> header;
350     std::string url {0};
351     std::string mimeType_ {};
352 };
353 
354 struct AVPlayStrategyTmp {
355     uint32_t preferredWidth;
356     uint32_t preferredHeight;
357     uint32_t preferredBufferDuration;
358     bool preferredHdr;
359     int32_t mutedMediaType = static_cast<int32_t>(MediaType::MEDIA_TYPE_MAX_COUNT);
360     std::string preferredAudioLanguage;
361     std::string preferredSubtitleLanguage;
362 };
363 
364 template<typename T>
365 class ObjectRefMap {
366 public:
367     static std::mutex allObjLock;
368     static std::map<T*, uint32_t> refMap;
369     static void Insert(T *obj);
370     static void Erase(T *obj);
371     static T *IncreaseRef(T *obj);
372     static void DecreaseRef(T *obj);
373 
374     explicit ObjectRefMap(T *obj);
375     ~ObjectRefMap();
376     T *GetPtr();
377 
378 private:
379     T *obj_ = nullptr;
380 };
381 
382 template <typename T>
383 std::mutex ObjectRefMap<T>::allObjLock;
384 
385 template <typename T>
386 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
387 
388 template <typename T>
Insert(T * obj)389 void ObjectRefMap<T>::Insert(T *obj)
390 {
391     std::lock_guard<std::mutex> lock(allObjLock);
392     refMap[obj] = 1;
393 }
394 
395 template <typename T>
Erase(T * obj)396 void ObjectRefMap<T>::Erase(T *obj)
397 {
398     std::lock_guard<std::mutex> lock(allObjLock);
399     auto it = refMap.find(obj);
400     if (it != refMap.end()) {
401         refMap.erase(it);
402     }
403 }
404 
405 template <typename T>
IncreaseRef(T * obj)406 T *ObjectRefMap<T>::IncreaseRef(T *obj)
407 {
408     std::lock_guard<std::mutex> lock(allObjLock);
409     if (refMap.count(obj)) {
410         refMap[obj]++;
411         return obj;
412     } else {
413         return nullptr;
414     }
415 }
416 
417 template <typename T>
DecreaseRef(T * obj)418 void ObjectRefMap<T>::DecreaseRef(T *obj)
419 {
420     std::lock_guard<std::mutex> lock(allObjLock);
421     if (refMap.count(obj) && --refMap[obj] == 0) {
422         refMap.erase(obj);
423         delete obj;
424         obj = nullptr;
425     }
426 }
427 
428 template <typename T>
ObjectRefMap(T * obj)429 ObjectRefMap<T>::ObjectRefMap(T *obj)
430 {
431     if (obj != nullptr) {
432         obj_ = ObjectRefMap::IncreaseRef(obj);
433     }
434 }
435 
436 template <typename T>
~ObjectRefMap()437 ObjectRefMap<T>::~ObjectRefMap()
438 {
439     if (obj_ != nullptr) {
440         ObjectRefMap::DecreaseRef(obj_);
441     }
442 }
443 
444 template <typename T>
GetPtr()445 T *ObjectRefMap<T>::GetPtr()
446 {
447     return obj_;
448 }
449 
450 } // namespace Media
451 } // namespace OHOS
452 #endif // COMMON_NAPI_H
453