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,
86 const AudioStandard::AudioDeviceDescriptor &deviceInfo);
87 static napi_status SetValueDeviceInfo(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
88 napi_value &result);
89 static napi_status SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
90 napi_value &result);
91 static napi_status SetDeviceDescriptors(const napi_env &env,
92 const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors, napi_value &result);
93 };
94
95 class MediaJsResult {
96 public:
97 virtual ~MediaJsResult() = default;
98 virtual napi_status GetJsResult(napi_env env, napi_value &result) = 0;
99 };
100
101 class MediaJsResultBoolean : public MediaJsResult {
102 public:
MediaJsResultBoolean(bool value)103 explicit MediaJsResultBoolean(bool value)
104 : value_(value)
105 {
106 }
107 ~MediaJsResultBoolean() = default;
GetJsResult(napi_env env,napi_value & result)108 napi_status GetJsResult(napi_env env, napi_value &result) override
109 {
110 return napi_get_boolean(env, value_, &result);
111 }
112 private:
113 bool value_;
114 };
115
116 class MediaJsResultInt : public MediaJsResult {
117 public:
MediaJsResultInt(int32_t value)118 explicit MediaJsResultInt(int32_t value)
119 : value_(value)
120 {
121 }
122 ~MediaJsResultInt() = default;
GetJsResult(napi_env env,napi_value & result)123 napi_status GetJsResult(napi_env env, napi_value &result) override
124 {
125 return napi_create_int32(env, value_, &result);
126 }
127 private:
128 int32_t value_;
129 };
130
131 class MediaJsResultString : public MediaJsResult {
132 public:
MediaJsResultString(const std::string & value)133 explicit MediaJsResultString(const std::string &value)
134 : value_(value)
135 {
136 }
137 ~MediaJsResultString() = default;
GetJsResult(napi_env env,napi_value & result)138 napi_status GetJsResult(napi_env env, napi_value &result) override
139 {
140 return napi_create_string_utf8(env, value_.c_str(), NAPI_AUTO_LENGTH, &result);
141 }
142
143 private:
144 std::string value_;
145 };
146
147 class MediaJsResultStringVector : public MediaJsResult {
148 public:
MediaJsResultStringVector(const std::vector<std::string> & value)149 explicit MediaJsResultStringVector(const std::vector<std::string> &value)
150 : value_(value)
151 {
152 }
153 ~MediaJsResultStringVector() = default;
154 napi_status GetJsResult(napi_env env, napi_value &result) override;
155
156 private:
157 std::vector<std::string> value_;
158 };
159
160 class MediaJsResultIntArray : public MediaJsResult {
161 public:
MediaJsResultIntArray(const std::vector<int32_t> & value)162 explicit MediaJsResultIntArray(const std::vector<int32_t> &value)
163 : value_(value)
164 {
165 }
166 ~MediaJsResultIntArray() = default;
167 napi_status GetJsResult(napi_env env, napi_value &result) override;
168
169 private:
170 std::vector<int32_t> value_;
171 };
172
173 class MediaJsResultArray : public MediaJsResult {
174 public:
MediaJsResultArray(const std::vector<Format> & value)175 explicit MediaJsResultArray(const std::vector<Format> &value)
176 : value_(value)
177 {
178 }
179 ~MediaJsResultArray() = default;
180 napi_status GetJsResult(napi_env env, napi_value &result) override;
181
182 private:
183 std::vector<Format> value_;
184 };
185
186 class MediaJsResultRange : public MediaJsResult {
187 public:
MediaJsResultRange(int32_t min,int32_t max)188 explicit MediaJsResultRange(int32_t min, int32_t max)
189 : min_(min),
190 max_(max)
191 {
192 }
193 ~MediaJsResultRange() = default;
GetJsResult(napi_env env,napi_value & result)194 napi_status GetJsResult(napi_env env, napi_value &result) override
195 {
196 napi_status status = napi_create_object(env, &result);
197 if (status != napi_ok) {
198 return status;
199 }
200
201 if (!CommonNapi::SetPropertyInt32(env, result, "min", min_)) {
202 return napi_invalid_arg;
203 }
204
205 if (!CommonNapi::SetPropertyInt32(env, result, "max", max_)) {
206 return napi_invalid_arg;
207 }
208
209 return napi_ok;
210 }
211 private:
212 int32_t min_;
213 int32_t max_;
214 };
215
216 class MediaJsResultInstance : public MediaJsResult {
217 public:
MediaJsResultInstance(const napi_ref & constructor)218 explicit MediaJsResultInstance(const napi_ref &constructor)
219 : constructor_(constructor)
220 {
221 }
222 ~MediaJsResultInstance() = default;
GetJsResult(napi_env env,napi_value & result)223 napi_status GetJsResult(napi_env env, napi_value &result) override
224 {
225 napi_value constructor = nullptr;
226 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
227 if (ret != napi_ok || constructor == nullptr) {
228 return ret;
229 }
230 return napi_new_instance(env, constructor, 0, nullptr, &result);
231 }
232
233 private:
234 napi_ref constructor_;
235 };
236
237 class AVCodecJsResultCtor : public MediaJsResult {
238 public:
AVCodecJsResultCtor(const napi_ref & constructor,int32_t isMimeType,const std::string & name)239 AVCodecJsResultCtor(const napi_ref &constructor, int32_t isMimeType, const std::string &name)
240 : constructor_(constructor),
241 isMimeType_(isMimeType),
242 name_(name)
243 {
244 }
245 ~AVCodecJsResultCtor() = default;
GetJsResult(napi_env env,napi_value & result)246 napi_status GetJsResult(napi_env env, napi_value &result) override
247 {
248 napi_value constructor = nullptr;
249 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
250 if (ret != napi_ok || constructor == nullptr) {
251 return ret;
252 }
253
254 napi_value args[2] = { nullptr };
255 ret = napi_create_string_utf8(env, name_.c_str(), NAPI_AUTO_LENGTH, &args[0]);
256 if (ret != napi_ok) {
257 return ret;
258 }
259
260 ret = napi_create_int32(env, isMimeType_, &args[1]);
261 if (ret != napi_ok) {
262 return ret;
263 }
264
265 return napi_new_instance(env, constructor, 2, args, &result); // The number of parameters is 2
266 }
267
268 private:
269 napi_ref constructor_;
270 int32_t isMimeType_ = 0;
271 std::string name_ = "";
272 };
273
274 class AVCodecJsResultFormat : public MediaJsResult {
275 public:
AVCodecJsResultFormat(const Format & format)276 explicit AVCodecJsResultFormat(const Format &format)
277 : format_(format)
278 {
279 }
280 ~AVCodecJsResultFormat() = default;
GetJsResult(napi_env env,napi_value & result)281 napi_status GetJsResult(napi_env env, napi_value &result) override
282 {
283 (void)CommonNapi::CreateFormatBufferByRef(env, format_, result);
284 return napi_ok;
285 }
286
287 private:
288 Format format_;
289 };
290
291 struct MediaAsyncContext {
292 explicit MediaAsyncContext(napi_env env);
293 virtual ~MediaAsyncContext();
294 static void CompleteCallback(napi_env env, napi_status status, void *data);
295 static void Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args);
296 static void CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args);
297 void SignError(int32_t code, const std::string &message, bool del = true);
298 std::string memoryTagHead = "safe";
299 napi_env env_;
300 napi_async_work work = nullptr;
301 napi_deferred deferred = nullptr;
302 napi_ref callbackRef = nullptr;
303 std::unique_ptr<MediaJsResult> JsResult;
304 bool errFlag = false;
305 int32_t errCode = 0;
306 std::string errMessage = "";
307 bool delFlag = true;
308 bool ctorFlag = false;
309 std::string memoryTagTail = "memory";
310 };
311
312 struct AutoRef {
AutoRefAutoRef313 AutoRef(napi_env env, napi_ref cb)
314 : env_(env), cb_(cb)
315 {
316 }
~AutoRefAutoRef317 ~AutoRef()
318 {
319 if (env_ != nullptr && cb_ != nullptr) {
320 (void)napi_delete_reference(env_, cb_);
321 }
322 }
323 napi_env env_;
324 napi_ref cb_;
325 };
326
327 struct AVDataSrcDescriptor {
328 int64_t fileSize = 0;
329 napi_value callback = nullptr;
330 };
331
332 class AVMediaSourceTmp {
333 public:
334 AVMediaSourceTmp() = default;
~AVMediaSourceTmp()335 ~AVMediaSourceTmp()
336 {
337 header.clear();
338 }
339
SetMimeType(const std::string & mimeType)340 void SetMimeType(const std::string& mimeType)
341 {
342 mimeType_ = mimeType;
343 }
344
GetMimeType()345 std::string GetMimeType() const
346 {
347 return mimeType_;
348 }
349
350 std::map<std::string, std::string> header;
351 std::string url {0};
352 std::string mimeType_ {};
353 };
354
355 struct AVPlayStrategyTmp {
356 uint32_t preferredWidth;
357 uint32_t preferredHeight;
358 uint32_t preferredBufferDuration;
359 bool preferredHdr;
360 int32_t mutedMediaType = static_cast<int32_t>(MediaType::MEDIA_TYPE_MAX_COUNT);
361 std::string preferredAudioLanguage;
362 std::string preferredSubtitleLanguage;
363 };
364
365 template<typename T>
366 class ObjectRefMap {
367 public:
368 static std::mutex allObjLock;
369 static std::map<T*, uint32_t> refMap;
370 static void Insert(T *obj);
371 static void Erase(T *obj);
372 static T *IncreaseRef(T *obj);
373 static void DecreaseRef(T *obj);
374
375 explicit ObjectRefMap(T *obj);
376 ~ObjectRefMap();
377 T *GetPtr();
378
379 private:
380 T *obj_ = nullptr;
381 };
382
383 template <typename T>
384 std::mutex ObjectRefMap<T>::allObjLock;
385
386 template <typename T>
387 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
388
389 template <typename T>
Insert(T * obj)390 void ObjectRefMap<T>::Insert(T *obj)
391 {
392 std::lock_guard<std::mutex> lock(allObjLock);
393 refMap[obj] = 1;
394 }
395
396 template <typename T>
Erase(T * obj)397 void ObjectRefMap<T>::Erase(T *obj)
398 {
399 std::lock_guard<std::mutex> lock(allObjLock);
400 auto it = refMap.find(obj);
401 if (it != refMap.end()) {
402 refMap.erase(it);
403 }
404 }
405
406 template <typename T>
IncreaseRef(T * obj)407 T *ObjectRefMap<T>::IncreaseRef(T *obj)
408 {
409 std::lock_guard<std::mutex> lock(allObjLock);
410 if (refMap.count(obj)) {
411 refMap[obj]++;
412 return obj;
413 } else {
414 return nullptr;
415 }
416 }
417
418 template <typename T>
DecreaseRef(T * obj)419 void ObjectRefMap<T>::DecreaseRef(T *obj)
420 {
421 std::lock_guard<std::mutex> lock(allObjLock);
422 if (refMap.count(obj) && --refMap[obj] == 0) {
423 refMap.erase(obj);
424 delete obj;
425 obj = nullptr;
426 }
427 }
428
429 template <typename T>
ObjectRefMap(T * obj)430 ObjectRefMap<T>::ObjectRefMap(T *obj)
431 {
432 if (obj != nullptr) {
433 obj_ = ObjectRefMap::IncreaseRef(obj);
434 }
435 }
436
437 template <typename T>
~ObjectRefMap()438 ObjectRefMap<T>::~ObjectRefMap()
439 {
440 if (obj_ != nullptr) {
441 ObjectRefMap::DecreaseRef(obj_);
442 }
443 }
444
445 template <typename T>
GetPtr()446 T *ObjectRefMap<T>::GetPtr()
447 {
448 return obj_;
449 }
450
451 } // namespace Media
452 } // namespace OHOS
453 #endif // COMMON_NAPI_H
454