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 <string>
20 #include <vector>
21 #include <unordered_map>
22 #include "meta/format.h"
23 #include "av_common.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "media_core.h"
27 #include "audio_info.h"
28 #include "audio_system_manager.h"
29
30 namespace OHOS {
31 namespace Media {
32 struct AVFileDescriptor;
33
34 class CommonNapi {
35 public:
36 CommonNapi() = delete;
37 ~CommonNapi() = delete;
38 static std::string GetStringArgument(napi_env env, napi_value value);
39 static bool CheckValueType(napi_env env, napi_value arg, napi_valuetype type);
40 static bool GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result);
41 static bool GetPropertyUint32(napi_env env, napi_value configObj, const std::string &type, uint32_t &result);
42 static bool GetPropertyInt64(napi_env env, napi_value configObj, const std::string &type, int64_t &result);
43 static bool GetPropertyDouble(napi_env env, napi_value configObj, const std::string &type, double &result);
44 static std::string GetPropertyString(napi_env env, napi_value configObj, const std::string &type);
45 static bool GetFdArgument(napi_env env, napi_value value, AVFileDescriptor &rawFd);
46 static napi_status FillErrorArgs(napi_env env, int32_t errCode, const napi_value &args);
47 static napi_status CreateError(napi_env env, int32_t errCode, const std::string &errMsg, napi_value &errVal);
48 static napi_ref CreateReference(napi_env env, napi_value arg);
49 static napi_deferred CreatePromise(napi_env env, napi_ref ref, napi_value &result);
50 static bool SetPropertyInt32(napi_env env, napi_value &obj, const std::string &key, int32_t value);
51 static bool SetPropertyDouble(napi_env env, napi_value &obj, const std::string &key, double value);
52 static bool SetPropertyBool(napi_env env, napi_value &obj, const std::string &key, bool value);
53 static bool SetPropertyString(napi_env env, napi_value &obj, const std::string &key, const std::string &value);
54 static napi_value CreateFormatBuffer(napi_env env, Format &format);
55 static bool CreateFormatBufferByRef(napi_env env, Format &format, napi_value &result);
56 static bool AddRangeProperty(napi_env env, napi_value obj, const std::string &name, int32_t min, int32_t max);
57 static bool AddArrayProperty(napi_env env, napi_value obj, const std::string &name,
58 const std::vector<int32_t> &vec);
59 static bool AddNumberPropInt32(napi_env env, napi_value obj, const std::string &key, int32_t value);
60 static bool AddNumberPropInt64(napi_env env, napi_value obj, const std::string &key, int64_t value);
61 static bool AddArrayInt(napi_env env, napi_value &array, const std::vector<int32_t> &vec);
62 static bool AddStringProperty(napi_env env, napi_value obj, const std::string &key, const std::string &value);
63 static bool GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result);
64
65 static void ConvertDeviceInfoToAudioDeviceDescriptor(
66 sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor, const AudioStandard::DeviceInfo &deviceInfo);
67 static napi_status SetValueDeviceInfo(const napi_env &env, const AudioStandard::DeviceInfo &deviceInfo,
68 napi_value &result);
69 static napi_status SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
70 napi_value &result);
71 static napi_status SetDeviceDescriptors(const napi_env &env,
72 const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors, napi_value &result);
73 };
74
75 class MediaJsResult {
76 public:
77 virtual ~MediaJsResult() = default;
78 virtual napi_status GetJsResult(napi_env env, napi_value &result) = 0;
79 };
80
81 class MediaJsResultBoolean : public MediaJsResult {
82 public:
MediaJsResultBoolean(bool value)83 explicit MediaJsResultBoolean(bool value)
84 : value_(value)
85 {
86 }
87 ~MediaJsResultBoolean() = default;
GetJsResult(napi_env env,napi_value & result)88 napi_status GetJsResult(napi_env env, napi_value &result) override
89 {
90 return napi_get_boolean(env, value_, &result);
91 }
92 private:
93 bool value_;
94 };
95
96 class MediaJsResultInt : public MediaJsResult {
97 public:
MediaJsResultInt(int32_t value)98 explicit MediaJsResultInt(int32_t value)
99 : value_(value)
100 {
101 }
102 ~MediaJsResultInt() = default;
GetJsResult(napi_env env,napi_value & result)103 napi_status GetJsResult(napi_env env, napi_value &result) override
104 {
105 return napi_create_int32(env, value_, &result);
106 }
107 private:
108 int32_t value_;
109 };
110
111 class MediaJsResultString : public MediaJsResult {
112 public:
MediaJsResultString(const std::string & value)113 explicit MediaJsResultString(const std::string &value)
114 : value_(value)
115 {
116 }
117 ~MediaJsResultString() = default;
GetJsResult(napi_env env,napi_value & result)118 napi_status GetJsResult(napi_env env, napi_value &result) override
119 {
120 return napi_create_string_utf8(env, value_.c_str(), NAPI_AUTO_LENGTH, &result);
121 }
122
123 private:
124 std::string value_;
125 };
126
127 class MediaJsResultStringVector : public MediaJsResult {
128 public:
MediaJsResultStringVector(const std::vector<std::string> & value)129 explicit MediaJsResultStringVector(const std::vector<std::string> &value)
130 : value_(value)
131 {
132 }
133 ~MediaJsResultStringVector() = default;
134 napi_status GetJsResult(napi_env env, napi_value &result) override;
135
136 private:
137 std::vector<std::string> value_;
138 };
139
140 class MediaJsResultArray : public MediaJsResult {
141 public:
MediaJsResultArray(const std::vector<Format> & value)142 explicit MediaJsResultArray(const std::vector<Format> &value)
143 : value_(value)
144 {
145 }
146 ~MediaJsResultArray() = default;
147 napi_status GetJsResult(napi_env env, napi_value &result) override;
148
149 private:
150 std::vector<Format> value_;
151 };
152
153 class MediaJsResultRange : public MediaJsResult {
154 public:
MediaJsResultRange(int32_t min,int32_t max)155 explicit MediaJsResultRange(int32_t min, int32_t max)
156 : min_(min),
157 max_(max)
158 {
159 }
160 ~MediaJsResultRange() = default;
GetJsResult(napi_env env,napi_value & result)161 napi_status GetJsResult(napi_env env, napi_value &result) override
162 {
163 napi_status status = napi_create_object(env, &result);
164 if (status != napi_ok) {
165 return status;
166 }
167
168 if (!CommonNapi::SetPropertyInt32(env, result, "min", min_)) {
169 return napi_invalid_arg;
170 }
171
172 if (!CommonNapi::SetPropertyInt32(env, result, "max", max_)) {
173 return napi_invalid_arg;
174 }
175
176 return napi_ok;
177 }
178 private:
179 int32_t min_;
180 int32_t max_;
181 };
182
183 class MediaJsResultInstance : public MediaJsResult {
184 public:
MediaJsResultInstance(const napi_ref & constructor)185 explicit MediaJsResultInstance(const napi_ref &constructor)
186 : constructor_(constructor)
187 {
188 }
189 ~MediaJsResultInstance() = default;
GetJsResult(napi_env env,napi_value & result)190 napi_status GetJsResult(napi_env env, napi_value &result) override
191 {
192 napi_value constructor = nullptr;
193 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
194 if (ret != napi_ok || constructor == nullptr) {
195 return ret;
196 }
197 return napi_new_instance(env, constructor, 0, nullptr, &result);
198 }
199
200 private:
201 napi_ref constructor_;
202 };
203
204 class AVCodecJsResultCtor : public MediaJsResult {
205 public:
AVCodecJsResultCtor(const napi_ref & constructor,int32_t isMimeType,const std::string & name)206 AVCodecJsResultCtor(const napi_ref &constructor, int32_t isMimeType, const std::string &name)
207 : constructor_(constructor),
208 isMimeType_(isMimeType),
209 name_(name)
210 {
211 }
212 ~AVCodecJsResultCtor() = default;
GetJsResult(napi_env env,napi_value & result)213 napi_status GetJsResult(napi_env env, napi_value &result) override
214 {
215 napi_value constructor = nullptr;
216 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
217 if (ret != napi_ok || constructor == nullptr) {
218 return ret;
219 }
220
221 napi_value args[2] = { nullptr };
222 ret = napi_create_string_utf8(env, name_.c_str(), NAPI_AUTO_LENGTH, &args[0]);
223 if (ret != napi_ok) {
224 return ret;
225 }
226
227 ret = napi_create_int32(env, isMimeType_, &args[1]);
228 if (ret != napi_ok) {
229 return ret;
230 }
231
232 return napi_new_instance(env, constructor, 2, args, &result); // The number of parameters is 2
233 }
234
235 private:
236 napi_ref constructor_;
237 int32_t isMimeType_ = 0;
238 std::string name_ = "";
239 };
240
241 class AVCodecJsResultFormat : public MediaJsResult {
242 public:
AVCodecJsResultFormat(const Format & format)243 explicit AVCodecJsResultFormat(const Format &format)
244 : format_(format)
245 {
246 }
247 ~AVCodecJsResultFormat() = default;
GetJsResult(napi_env env,napi_value & result)248 napi_status GetJsResult(napi_env env, napi_value &result) override
249 {
250 (void)CommonNapi::CreateFormatBufferByRef(env, format_, result);
251 return napi_ok;
252 }
253
254 private:
255 Format format_;
256 };
257
258 struct MediaAsyncContext {
259 explicit MediaAsyncContext(napi_env env);
260 virtual ~MediaAsyncContext();
261 static void CompleteCallback(napi_env env, napi_status status, void *data);
262 static void Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args);
263 static void CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args);
264 void SignError(int32_t code, const std::string &message, bool del = true);
265 std::string memoryTagHead = "safe";
266 napi_env env_;
267 napi_async_work work = nullptr;
268 napi_deferred deferred = nullptr;
269 napi_ref callbackRef = nullptr;
270 std::unique_ptr<MediaJsResult> JsResult;
271 bool errFlag = false;
272 int32_t errCode = 0;
273 std::string errMessage = "";
274 bool delFlag = true;
275 bool ctorFlag = false;
276 std::string memoryTagTail = "memory";
277 };
278
279 struct AutoRef {
AutoRefAutoRef280 AutoRef(napi_env env, napi_ref cb)
281 : env_(env), cb_(cb)
282 {
283 }
~AutoRefAutoRef284 ~AutoRef()
285 {
286 if (env_ != nullptr && cb_ != nullptr) {
287 (void)napi_delete_reference(env_, cb_);
288 }
289 }
290 napi_env env_;
291 napi_ref cb_;
292 };
293
294 struct AVDataSrcDescriptor {
295 int64_t fileSize = 0;
296 napi_value callback = nullptr;
297 };
298
299 template<typename T>
300 class ObjectRefMap {
301 public:
302 static std::mutex allObjLock;
303 static std::map<T*, uint32_t> refMap;
304 static void Insert(T *obj);
305 static void Erase(T *obj);
306 static T *IncreaseRef(T *obj);
307 static void DecreaseRef(T *obj);
308
309 ObjectRefMap(T *obj);
310 ~ObjectRefMap();
311 T *GetPtr();
312
313 private:
314 T *obj_ = nullptr;
315 };
316
317 template <typename T>
318 std::mutex ObjectRefMap<T>::allObjLock;
319
320 template <typename T>
321 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
322
323 template <typename T>
Insert(T * obj)324 void ObjectRefMap<T>::Insert(T *obj)
325 {
326 std::lock_guard<std::mutex> lock(allObjLock);
327 refMap[obj] = 1;
328 }
329
330 template <typename T>
Erase(T * obj)331 void ObjectRefMap<T>::Erase(T *obj)
332 {
333 std::lock_guard<std::mutex> lock(allObjLock);
334 auto it = refMap.find(obj);
335 if (it != refMap.end()) {
336 refMap.erase(it);
337 }
338 }
339
340 template <typename T>
IncreaseRef(T * obj)341 T *ObjectRefMap<T>::IncreaseRef(T *obj)
342 {
343 std::lock_guard<std::mutex> lock(allObjLock);
344 if (refMap.count(obj)) {
345 refMap[obj]++;
346 return obj;
347 } else {
348 return nullptr;
349 }
350 }
351
352 template <typename T>
DecreaseRef(T * obj)353 void ObjectRefMap<T>::DecreaseRef(T *obj)
354 {
355 std::lock_guard<std::mutex> lock(allObjLock);
356 if (refMap.count(obj) && --refMap[obj] == 0) {
357 refMap.erase(obj);
358 delete obj;
359 obj = nullptr;
360 }
361 }
362
363 template <typename T>
ObjectRefMap(T * obj)364 ObjectRefMap<T>::ObjectRefMap(T *obj)
365 {
366 if (obj != nullptr) {
367 obj_ = ObjectRefMap::IncreaseRef(obj);
368 }
369 }
370
371 template <typename T>
~ObjectRefMap()372 ObjectRefMap<T>::~ObjectRefMap()
373 {
374 if (obj_ != nullptr) {
375 ObjectRefMap::DecreaseRef(obj_);
376 }
377 }
378
379 template <typename T>
GetPtr()380 T *ObjectRefMap<T>::GetPtr()
381 {
382 return obj_;
383 }
384
385 } // namespace Media
386 } // namespace OHOS
387 #endif // COMMON_NAPI_H
388