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