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 AVPlayMediaStreamTmp;
37 struct AVDataSrcDescriptor;
38 class AVMediaSourceTmp;
39 /**
40 * customInfo max count
41 */
42 constexpr uint32_t MAX_COUNT = 500;
43 /**
44 * NOTE: use on AVRecorderConfig.metadata.customInfo
45 */
46 constexpr uint32_t CUSTOM_MAX_LENGTH = 1001;
47 constexpr size_t MAX_ARRAY_LENGTH = 100;
48 class CommonNapi {
49 public:
50 CommonNapi() = delete;
51 ~CommonNapi() = delete;
52 static std::string GetStringArgument(napi_env env, napi_value value, size_t maxLength = PATH_MAX);
53 static bool GetIntArrayArgument(
54 napi_env env, napi_value value, std::vector<int32_t> &vec, size_t maxLength = MAX_ARRAY_LENGTH);
55 static bool CheckValueType(napi_env env, napi_value arg, napi_valuetype type);
56 static bool CheckhasNamedProperty(napi_env env, napi_value arg, std::string type);
57 static bool GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result);
58 static bool GetPropertyUint32(napi_env env, napi_value configObj, const std::string &type, uint32_t &result);
59 static bool GetPropertyInt64(napi_env env, napi_value configObj, const std::string &type, int64_t &result);
60 static bool GetPropertyDouble(napi_env env, napi_value configObj, const std::string &type, double &result);
61 static std::string GetPropertyString(napi_env env, napi_value configObj, const std::string &type);
62 static bool GetPropertyArrayBuffer(napi_env env, napi_value configObj, void **data, size_t* length);
63 // support Record<string, string>
64 static napi_status GetPropertyRecord(napi_env env, napi_value in, Meta &meta, std::string type);
65 static bool GetPropertyMap(napi_env env, napi_value value, std::map<std::string, std::string>& map);
66 static bool GetFdArgument(napi_env env, napi_value value, AVFileDescriptor &rawFd);
67 static bool GetPlayStrategy(napi_env env, napi_value value, AVPlayStrategyTmp &playStrategy);
68 static bool GetPlayMediaStreamData(napi_env env, napi_value value, AVPlayMediaStreamTmp &mediaStream);
69 static napi_status FillErrorArgs(napi_env env, int32_t errCode, const napi_value &args);
70 static napi_status CreateError(napi_env env, int32_t errCode, const std::string &errMsg, napi_value &errVal);
71 static napi_ref CreateReference(napi_env env, napi_value arg);
72 static napi_deferred CreatePromise(napi_env env, napi_ref ref, napi_value &result);
73 static bool SetPropertyByValueType(napi_env env, napi_value &obj, std::shared_ptr<Meta> &meta, std::string key);
74 static bool SetPropertyInt32(napi_env env, napi_value &obj, const std::string &key, int32_t value);
75 static bool SetPropertyInt64(napi_env env, napi_value &obj, const std::string &key, int64_t value);
76 static bool SetPropertyDouble(napi_env env, napi_value &obj, const std::string &key, double value);
77 static bool SetPropertyBool(napi_env env, napi_value &obj, const std::string &key, bool value);
78 static bool SetPropertyString(napi_env env, napi_value &obj, const std::string &key, const std::string &value);
79 static bool SetPropertyArrayBuffer(
80 const napi_env &env, napi_value &result, const std::string &fieldStr, size_t bufferLen, uint8_t *bufferData);
81 static napi_value CreateFormatBuffer(napi_env env, Format &format);
82 static bool CreateFormatBufferByRef(napi_env env, Format &format, napi_value &result);
83 static bool AddRangeProperty(napi_env env, napi_value obj, const std::string &name, int32_t min, int32_t max);
84 static bool AddArrayProperty(napi_env env, napi_value obj, const std::string &name,
85 const std::vector<int32_t> &vec);
86 static bool AddNumberPropInt32(napi_env env, napi_value obj, const std::string &key, int32_t value);
87 static bool AddNumberPropInt64(napi_env env, napi_value obj, const std::string &key, int64_t value);
88 static bool AddArrayInt(napi_env env, napi_value &array, const std::vector<int32_t> &vec);
89 static bool AddStringProperty(napi_env env, napi_value obj, const std::string &key, const std::string &value);
90 static bool GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result);
91
92 static void ConvertDeviceInfoToAudioDeviceDescriptor(
93 std::shared_ptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor,
94 const AudioStandard::AudioDeviceDescriptor &deviceInfo);
95 static napi_status SetValueDeviceInfo(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
96 napi_value &result);
97 static napi_status SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
98 napi_value &result);
99 static napi_status SetDeviceDescriptors(const napi_env &env,
100 const std::vector<std::shared_ptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors,
101 napi_value &result);
102 static napi_value ThrowError(napi_env env, const int32_t errCode, const std::string errMsg);
103 };
104
105 class MediaJsResult {
106 public:
107 virtual ~MediaJsResult() = default;
108 virtual napi_status GetJsResult(napi_env env, napi_value &result) = 0;
109 };
110
111 struct NapiTypeCheckUnit {
112 napi_env env;
113 napi_value param;
114 napi_valuetype expectedType;
115 };
116
117 class MediaJsResultBoolean : public MediaJsResult {
118 public:
MediaJsResultBoolean(bool value)119 explicit MediaJsResultBoolean(bool value)
120 : value_(value)
121 {
122 }
123 ~MediaJsResultBoolean() = default;
GetJsResult(napi_env env,napi_value & result)124 napi_status GetJsResult(napi_env env, napi_value &result) override
125 {
126 return napi_get_boolean(env, value_, &result);
127 }
128 private:
129 bool value_;
130 };
131
132 class MediaJsResultInt : public MediaJsResult {
133 public:
MediaJsResultInt(int32_t value)134 explicit MediaJsResultInt(int32_t value)
135 : value_(value)
136 {
137 }
138 ~MediaJsResultInt() = default;
GetJsResult(napi_env env,napi_value & result)139 napi_status GetJsResult(napi_env env, napi_value &result) override
140 {
141 return napi_create_int32(env, value_, &result);
142 }
143 private:
144 int32_t value_;
145 };
146
147 class MediaJsResultString : public MediaJsResult {
148 public:
MediaJsResultString(const std::string & value)149 explicit MediaJsResultString(const std::string &value)
150 : value_(value)
151 {
152 }
153 ~MediaJsResultString() = default;
GetJsResult(napi_env env,napi_value & result)154 napi_status GetJsResult(napi_env env, napi_value &result) override
155 {
156 return napi_create_string_utf8(env, value_.c_str(), NAPI_AUTO_LENGTH, &result);
157 }
158
159 private:
160 std::string value_;
161 };
162
163 class MediaJsResultStringVector : public MediaJsResult {
164 public:
MediaJsResultStringVector(const std::vector<std::string> & value)165 explicit MediaJsResultStringVector(const std::vector<std::string> &value)
166 : value_(value)
167 {
168 }
169 ~MediaJsResultStringVector() = default;
170 napi_status GetJsResult(napi_env env, napi_value &result) override;
171
172 private:
173 std::vector<std::string> value_;
174 };
175
176 class MediaJsResultIntArray : public MediaJsResult {
177 public:
MediaJsResultIntArray(const std::vector<int32_t> & value)178 explicit MediaJsResultIntArray(const std::vector<int32_t> &value)
179 : value_(value)
180 {
181 }
182 ~MediaJsResultIntArray() = default;
183 napi_status GetJsResult(napi_env env, napi_value &result) override;
184
185 private:
186 std::vector<int32_t> value_;
187 };
188
189 class MediaJsResultArray : public MediaJsResult {
190 public:
MediaJsResultArray(const std::vector<Format> & value)191 explicit MediaJsResultArray(const std::vector<Format> &value)
192 : value_(value)
193 {
194 }
195 ~MediaJsResultArray() = default;
196 napi_status GetJsResult(napi_env env, napi_value &result) override;
197
198 private:
199 std::vector<Format> value_;
200 };
201
202 class MediaJsResultRange : public MediaJsResult {
203 public:
MediaJsResultRange(int32_t min,int32_t max)204 explicit MediaJsResultRange(int32_t min, int32_t max)
205 : min_(min),
206 max_(max)
207 {
208 }
209 ~MediaJsResultRange() = default;
GetJsResult(napi_env env,napi_value & result)210 napi_status GetJsResult(napi_env env, napi_value &result) override
211 {
212 napi_status status = napi_create_object(env, &result);
213 if (status != napi_ok) {
214 return status;
215 }
216
217 if (!CommonNapi::SetPropertyInt32(env, result, "min", min_)) {
218 return napi_invalid_arg;
219 }
220
221 if (!CommonNapi::SetPropertyInt32(env, result, "max", max_)) {
222 return napi_invalid_arg;
223 }
224
225 return napi_ok;
226 }
227 private:
228 int32_t min_;
229 int32_t max_;
230 };
231
232 class MediaJsResultInstance : public MediaJsResult {
233 public:
MediaJsResultInstance(const napi_ref & constructor)234 explicit MediaJsResultInstance(const napi_ref &constructor)
235 : constructor_(constructor)
236 {
237 }
238 ~MediaJsResultInstance() = default;
GetJsResult(napi_env env,napi_value & result)239 napi_status GetJsResult(napi_env env, napi_value &result) override
240 {
241 napi_value constructor = nullptr;
242 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
243 if (ret != napi_ok || constructor == nullptr) {
244 return ret;
245 }
246 return napi_new_instance(env, constructor, 0, nullptr, &result);
247 }
248
249 private:
250 napi_ref constructor_;
251 };
252
253 class AVCodecJsResultCtor : public MediaJsResult {
254 public:
AVCodecJsResultCtor(const napi_ref & constructor,int32_t isMimeType,const std::string & name)255 AVCodecJsResultCtor(const napi_ref &constructor, int32_t isMimeType, const std::string &name)
256 : constructor_(constructor),
257 isMimeType_(isMimeType),
258 name_(name)
259 {
260 }
261 ~AVCodecJsResultCtor() = default;
GetJsResult(napi_env env,napi_value & result)262 napi_status GetJsResult(napi_env env, napi_value &result) override
263 {
264 napi_value constructor = nullptr;
265 napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
266 if (ret != napi_ok || constructor == nullptr) {
267 return ret;
268 }
269
270 napi_value args[2] = { nullptr };
271 ret = napi_create_string_utf8(env, name_.c_str(), NAPI_AUTO_LENGTH, &args[0]);
272 if (ret != napi_ok) {
273 return ret;
274 }
275
276 ret = napi_create_int32(env, isMimeType_, &args[1]);
277 if (ret != napi_ok) {
278 return ret;
279 }
280
281 return napi_new_instance(env, constructor, 2, args, &result); // The number of parameters is 2
282 }
283
284 private:
285 napi_ref constructor_;
286 int32_t isMimeType_ = 0;
287 std::string name_ = "";
288 };
289
290 class AVCodecJsResultFormat : public MediaJsResult {
291 public:
AVCodecJsResultFormat(const Format & format)292 explicit AVCodecJsResultFormat(const Format &format)
293 : format_(format)
294 {
295 }
296 ~AVCodecJsResultFormat() = default;
GetJsResult(napi_env env,napi_value & result)297 napi_status GetJsResult(napi_env env, napi_value &result) override
298 {
299 (void)CommonNapi::CreateFormatBufferByRef(env, format_, result);
300 return napi_ok;
301 }
302
303 private:
304 Format format_;
305 };
306
307 struct MediaAsyncContext {
308 explicit MediaAsyncContext(napi_env env);
309 virtual ~MediaAsyncContext();
310 static void CompleteCallback(napi_env env, napi_status status, void *data);
311 static void Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args);
312 static void CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args);
313 static napi_status SendCompleteEvent(napi_env env, MediaAsyncContext *ctx, napi_event_priority prio);
314 void SignError(int32_t code, const std::string &message, bool del = true);
315 std::string memoryTagHead = "safe";
316 napi_env env_;
317 napi_async_work work = nullptr;
318 napi_deferred deferred = nullptr;
319 napi_ref callbackRef = nullptr;
320 std::unique_ptr<MediaJsResult> JsResult;
321 bool errFlag = false;
322 int32_t errCode = 0;
323 std::string errMessage = "";
324 bool delFlag = true;
325 bool ctorFlag = false;
326 std::string memoryTagTail = "memory";
327 };
328
329 struct AutoRef {
AutoRefAutoRef330 AutoRef(napi_env env, napi_ref cb)
331 : env_(env), cb_(cb)
332 {
333 }
~AutoRefAutoRef334 ~AutoRef()
335 {
336 if (env_ != nullptr && cb_ != nullptr) {
337 (void)napi_delete_reference(env_, cb_);
338 }
339 }
340 napi_env env_;
341 napi_ref cb_;
342 };
343
344 struct AVDataSrcDescriptor {
345 int64_t fileSize = 0;
346 napi_value callback = nullptr;
347 };
348
349 class AVMediaSourceTmp {
350 public:
351 AVMediaSourceTmp() = default;
~AVMediaSourceTmp()352 ~AVMediaSourceTmp()
353 {
354 header.clear();
355 }
356
SetMimeType(const std::string & mimeType)357 void SetMimeType(const std::string& mimeType)
358 {
359 mimeType_ = mimeType;
360 }
361
GetMimeType()362 std::string GetMimeType() const
363 {
364 return mimeType_;
365 }
366
AddAVPlayMediaStreamTmp(const AVPlayMediaStreamTmp & avPlayMediaStreamTmp)367 void AddAVPlayMediaStreamTmp(const AVPlayMediaStreamTmp& avPlayMediaStreamTmp)
368 {
369 mediaStreamVec_.push_back(avPlayMediaStreamTmp);
370 }
371
getAVPlayMediaStreamTmpList()372 const std::vector<AVPlayMediaStreamTmp>& getAVPlayMediaStreamTmpList()
373 {
374 return mediaStreamVec_;
375 }
376
377 std::map<std::string, std::string> header;
378 std::string url {};
379 std::string mimeType_ {};
380 private:
381 std::vector<AVPlayMediaStreamTmp> mediaStreamVec_;
382 };
383
384 struct AVPlayStrategyTmp {
385 uint32_t preferredWidth;
386 uint32_t preferredHeight;
387 uint32_t preferredBufferDuration;
388 bool preferredHdr;
389 bool showFirstFrameOnPrepare;
390 bool enableSuperResolution;
391 int32_t mutedMediaType = static_cast<int32_t>(MediaType::MEDIA_TYPE_MAX_COUNT);
392 std::string preferredAudioLanguage;
393 std::string preferredSubtitleLanguage;
394 double preferredBufferDurationForPlaying;
395 double thresholdForAutoQuickPlay;
396 bool isSetBufferDurationForPlaying {true};
397 bool isSetThresholdForAutoQuickPlay {true};
398 };
399
400 struct AVPlayMediaStreamTmp {
401 std::string url;
402 uint32_t width;
403 uint32_t height;
404 uint32_t bitrate;
405 };
406
407 template<typename T>
408 class ObjectRefMap {
409 public:
410 static std::mutex allObjLock;
411 static std::map<T*, uint32_t> refMap;
412 static void Insert(T *obj);
413 static void Erase(T *obj);
414 static T *IncreaseRef(T *obj);
415 static void DecreaseRef(T *obj);
416
417 explicit ObjectRefMap(T *obj);
418 ~ObjectRefMap();
419 T *GetPtr();
420
421 private:
422 T *obj_ = nullptr;
423 };
424
425 template <typename T>
426 std::mutex ObjectRefMap<T>::allObjLock;
427
428 template <typename T>
429 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
430
431 template <typename T>
Insert(T * obj)432 void ObjectRefMap<T>::Insert(T *obj)
433 {
434 std::lock_guard<std::mutex> lock(allObjLock);
435 refMap[obj] = 1;
436 }
437
438 template <typename T>
Erase(T * obj)439 void ObjectRefMap<T>::Erase(T *obj)
440 {
441 std::lock_guard<std::mutex> lock(allObjLock);
442 auto it = refMap.find(obj);
443 if (it != refMap.end()) {
444 refMap.erase(it);
445 }
446 }
447
448 template <typename T>
IncreaseRef(T * obj)449 T *ObjectRefMap<T>::IncreaseRef(T *obj)
450 {
451 std::lock_guard<std::mutex> lock(allObjLock);
452 if (refMap.count(obj)) {
453 refMap[obj]++;
454 return obj;
455 } else {
456 return nullptr;
457 }
458 }
459
460 template <typename T>
DecreaseRef(T * obj)461 void ObjectRefMap<T>::DecreaseRef(T *obj)
462 {
463 std::lock_guard<std::mutex> lock(allObjLock);
464 if (refMap.count(obj) && --refMap[obj] == 0) {
465 refMap.erase(obj);
466 delete obj;
467 obj = nullptr;
468 }
469 }
470
471 template <typename T>
ObjectRefMap(T * obj)472 ObjectRefMap<T>::ObjectRefMap(T *obj)
473 {
474 if (obj != nullptr) {
475 obj_ = ObjectRefMap::IncreaseRef(obj);
476 }
477 }
478
479 template <typename T>
~ObjectRefMap()480 ObjectRefMap<T>::~ObjectRefMap()
481 {
482 if (obj_ != nullptr) {
483 ObjectRefMap::DecreaseRef(obj_);
484 }
485 }
486
487 template <typename T>
GetPtr()488 T *ObjectRefMap<T>::GetPtr()
489 {
490 return obj_;
491 }
492
493 } // namespace Media
494 } // namespace OHOS
495 #endif // COMMON_NAPI_H
496