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