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