1  /*
2   * Copyright (C) 2022 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  #include <map>
17  #include <iostream>
18  #include <sstream>
19  #include <iomanip>
20  #include <uv.h>
21  #include "avplayer_napi.h"
22  #include "media_errors.h"
23  #include "media_log.h"
24  #include "player.h"
25  #include "scope_guard.h"
26  #include "event_queue.h"
27  #include "avplayer_callback.h"
28  
29  namespace {
30  constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "AVPlayerCallback" };
31  }
32  
33  namespace OHOS {
34  namespace Media {
35  class NapiCallback {
36  public:
37      struct Base {
38          std::weak_ptr<AutoRef> callback;
39          std::string callbackName = "unknown";
40          Base() = default;
41          virtual ~Base() = default;
UvWorkOHOS::Media::NapiCallback::Base42          virtual void UvWork()
43          {
44              std::shared_ptr<AutoRef> ref = callback.lock();
45              CHECK_AND_RETURN_LOG(ref != nullptr,
46                  "%{public}s AutoRef is nullptr", callbackName.c_str());
47  
48              napi_handle_scope scope = nullptr;
49              napi_open_handle_scope(ref->env_, &scope);
50              CHECK_AND_RETURN_LOG(scope != nullptr,
51                  "%{public}s scope is nullptr", callbackName.c_str());
52              ON_SCOPE_EXIT(0) {
53                  napi_close_handle_scope(ref->env_, scope);
54              };
55  
56              napi_value jsCallback = nullptr;
57              napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
58              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
59                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
60  
61              // Call back function
62              napi_value result = nullptr;
63              status = napi_call_function(ref->env_, nullptr, jsCallback, 0, nullptr, &result);
64              CHECK_AND_RETURN_LOG(status == napi_ok,
65                  "%{public}s failed to napi_call_function", callbackName.c_str());
66          }
JsCallbackOHOS::Media::NapiCallback::Base67          virtual void JsCallback()
68          {
69              UvWork();
70              delete this;
71          }
72      };
73  
74      struct Error : public Base {
75          std::string errorMsg = "unknown";
76          MediaServiceExtErrCodeAPI9 errorCode = MSERR_EXT_API9_UNSUPPORT_FORMAT;
UvWorkOHOS::Media::NapiCallback::Error77          void UvWork() override
78          {
79              std::shared_ptr<AutoRef> errorRef = callback.lock();
80              CHECK_AND_RETURN_LOG(errorRef != nullptr,
81                  "%{public}s AutoRef is nullptr", callbackName.c_str());
82  
83              napi_handle_scope scope = nullptr;
84              napi_open_handle_scope(errorRef->env_, &scope);
85              CHECK_AND_RETURN_LOG(scope != nullptr,
86                  "%{public}s scope is nullptr", callbackName.c_str());
87              ON_SCOPE_EXIT(0) {
88                  napi_close_handle_scope(errorRef->env_, scope);
89              };
90  
91              napi_value jsCallback = nullptr;
92              napi_status napiStatus = napi_get_reference_value(errorRef->env_, errorRef->cb_, &jsCallback);
93              CHECK_AND_RETURN_LOG(napiStatus == napi_ok && jsCallback != nullptr,
94                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
95  
96              napi_value args[1] = {nullptr};
97              (void)CommonNapi::CreateError(errorRef->env_, errorCode, errorMsg, args[0]);
98  
99              // Call back function
100              napi_value result = nullptr;
101              napiStatus = napi_call_function(errorRef->env_, nullptr, jsCallback, 1, args, &result);
102              CHECK_AND_RETURN_LOG(napiStatus == napi_ok,
103                  "%{public}s failed to napi_call_function", callbackName.c_str());
104          }
105      };
106  
107      struct Int : public Base {
108          int32_t value = 0;
UvWorkOHOS::Media::NapiCallback::Int109          void UvWork() override
110          {
111              std::shared_ptr<AutoRef> intRef = callback.lock();
112              CHECK_AND_RETURN_LOG(intRef != nullptr,
113                  "%{public}s AutoRef is nullptr", callbackName.c_str());
114  
115              napi_handle_scope scope = nullptr;
116              napi_open_handle_scope(intRef->env_, &scope);
117              CHECK_AND_RETURN_LOG(scope != nullptr,
118                  "%{public}s scope is nullptr", callbackName.c_str());
119              ON_SCOPE_EXIT(0) {
120                  napi_close_handle_scope(intRef->env_, scope);
121              };
122  
123              napi_value jsCallback = nullptr;
124              napi_status status = napi_get_reference_value(intRef->env_, intRef->cb_, &jsCallback);
125              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
126                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
127  
128              napi_value args[1] = {nullptr}; // callback: (int)
129              (void)napi_create_int32(intRef->env_, value, &args[0]);
130  
131              napi_value result = nullptr;
132              status = napi_call_function(intRef->env_, nullptr, jsCallback, 1, args, &result);
133              CHECK_AND_RETURN_LOG(status == napi_ok,
134                  "%{public}s failed to napi_call_function", callbackName.c_str());
135          }
136      };
137  
138      struct IntVec : public Base {
139          std::vector<int32_t> valueVec;
UvWorkOHOS::Media::NapiCallback::IntVec140          void UvWork() override
141          {
142              std::shared_ptr<AutoRef> intVecRef = callback.lock();
143              CHECK_AND_RETURN_LOG(intVecRef != nullptr,
144                  "%{public}s AutoRef is nullptr", callbackName.c_str());
145  
146              napi_handle_scope scope = nullptr;
147              napi_open_handle_scope(intVecRef->env_, &scope);
148              CHECK_AND_RETURN_LOG(scope != nullptr,
149                  "%{public}s scope is nullptr", callbackName.c_str());
150              ON_SCOPE_EXIT(0) {
151                  napi_close_handle_scope(intVecRef->env_, scope);
152              };
153  
154              napi_value jsCallback = nullptr;
155              napi_status status = napi_get_reference_value(intVecRef->env_, intVecRef->cb_, &jsCallback);
156              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
157                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
158  
159              napi_value args[2] = {nullptr}; // callback: (int, int)
160              (void)napi_create_int32(intVecRef->env_, valueVec[0], &args[0]);
161              (void)napi_create_int32(intVecRef->env_, valueVec[1], &args[1]);
162  
163              const int32_t argCount = static_cast<int32_t>(valueVec.size());
164              napi_value result = nullptr;
165              status = napi_call_function(intVecRef->env_, nullptr, jsCallback, argCount, args, &result);
166              CHECK_AND_RETURN_LOG(status == napi_ok,
167                  "%{public}s failed to napi_call_function", callbackName.c_str());
168          }
169      };
170  
171      struct IntArray : public Base {
172          std::vector<int32_t> valueVec;
UvWorkOHOS::Media::NapiCallback::IntArray173          void UvWork() override
174          {
175              std::shared_ptr<AutoRef> intArrayRef = callback.lock();
176              CHECK_AND_RETURN_LOG(intArrayRef != nullptr,
177                  "%{public}s AutoRef is nullptr", callbackName.c_str());
178  
179              napi_handle_scope scope = nullptr;
180              napi_open_handle_scope(intArrayRef->env_, &scope);
181              CHECK_AND_RETURN_LOG(scope != nullptr,
182                  "%{public}s scope is nullptr", callbackName.c_str());
183              ON_SCOPE_EXIT(0) {
184                  napi_close_handle_scope(intArrayRef->env_, scope);
185              };
186  
187              napi_value jsCallback = nullptr;
188              napi_status status = napi_get_reference_value(intArrayRef->env_, intArrayRef->cb_, &jsCallback);
189              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
190                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
191  
192              napi_value array = nullptr;
193              (void)napi_create_array_with_length(intArrayRef->env_, valueVec.size(), &array);
194  
195              for (uint32_t i = 0; i < valueVec.size(); i++) {
196                  napi_value number = nullptr;
197                  (void)napi_create_int32(intArrayRef->env_, valueVec.at(i), &number);
198                  (void)napi_set_element(intArrayRef->env_, array, i, number);
199              }
200  
201              napi_value result = nullptr;
202              napi_value args[1] = {array};
203              status = napi_call_function(intArrayRef->env_, nullptr, jsCallback, 1, args, &result);
204              CHECK_AND_RETURN_LOG(status == napi_ok,
205                  "%{public}s failed to napi_call_function", callbackName.c_str());
206          }
207      };
208  
209      struct Double : public Base {
210          double value = 0.0;
UvWorkOHOS::Media::NapiCallback::Double211          void UvWork() override
212          {
213              std::shared_ptr<AutoRef> doubleRef = callback.lock();
214              CHECK_AND_RETURN_LOG(doubleRef != nullptr,
215                  "%{public}s AutoRef is nullptr", callbackName.c_str());
216  
217              napi_handle_scope scope = nullptr;
218              napi_open_handle_scope(doubleRef->env_, &scope);
219              CHECK_AND_RETURN_LOG(scope != nullptr,
220                  "%{public}s scope is nullptr", callbackName.c_str());
221              ON_SCOPE_EXIT(0) {
222                  napi_close_handle_scope(doubleRef->env_, scope);
223              };
224  
225              napi_value jsCallback = nullptr;
226              napi_status status = napi_get_reference_value(doubleRef->env_, doubleRef->cb_, &jsCallback);
227              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
228                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
229  
230              napi_value args[1] = {nullptr};
231              (void)napi_create_double(doubleRef->env_, value, &args[0]);
232  
233              napi_value result = nullptr;
234              status = napi_call_function(doubleRef->env_, nullptr, jsCallback, 1, args, &result);
235              CHECK_AND_RETURN_LOG(status == napi_ok,
236                  "%{public}s failed to napi_call_function", callbackName.c_str());
237          }
238      };
239  
240      struct FloatArray : public Base {
241          std::vector<float>valueVec;
UvWorkOHOS::Media::NapiCallback::FloatArray242          void UvWork() override
243          {
244              std::shared_ptr<AutoRef> floatArrayRef = callback.lock();
245              CHECK_AND_RETURN_LOG(floatArrayRef != nullptr,
246                  "%{public}s AutoRef is nullptr", callbackName.c_str());
247  
248              napi_handle_scope scope = nullptr;
249              napi_open_handle_scope(floatArrayRef->env_, &scope);
250              CHECK_AND_RETURN_LOG(scope != nullptr,
251                  "%{public}s scope is nullptr", callbackName.c_str());
252              ON_SCOPE_EXIT(0) {
253                  napi_close_handle_scope(floatArrayRef->env_, scope);
254              };
255  
256              napi_value jsCallback = nullptr;
257              napi_status status = napi_get_reference_value(floatArrayRef->env_, floatArrayRef->cb_, &jsCallback);
258              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
259                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
260  
261              napi_value array = nullptr;
262              (void)napi_create_array_with_length(floatArrayRef->env_, valueVec.size(), &array);
263  
264              for (uint32_t i = 0; i < valueVec.size(); i++) {
265                  napi_value number = nullptr;
266                  (void)napi_create_double(floatArrayRef->env_, valueVec.at(i), &number);
267                  (void)napi_set_element(floatArrayRef->env_, array, i, number);
268              }
269  
270              napi_value result = nullptr;
271              napi_value args[1] = {array};
272              status = napi_call_function(floatArrayRef->env_, nullptr, jsCallback, 1, args, &result);
273              CHECK_AND_RETURN_LOG(status == napi_ok,
274                  "%{public}s failed to napi_call_function", callbackName.c_str());
275          }
276      };
277  
278      struct SubtitleProperty : public Base {
279          std::string text;
UvWorkOHOS::Media::NapiCallback::SubtitleProperty280          void UvWork() override
281          {
282              std::shared_ptr<AutoRef> subtitleRef = callback.lock();
283              CHECK_AND_RETURN_LOG(subtitleRef != nullptr,
284                  "%{public}s AutoRef is nullptr", callbackName.c_str());
285  
286              napi_handle_scope scope = nullptr;
287              napi_open_handle_scope(subtitleRef->env_, &scope);
288              CHECK_AND_RETURN_LOG(scope != nullptr,
289                  "%{public}s scope is nullptr", callbackName.c_str());
290              ON_SCOPE_EXIT(0) {
291                  napi_close_handle_scope(subtitleRef->env_, scope);
292              };
293  
294              napi_value jsCallback = nullptr;
295              napi_status status = napi_get_reference_value(subtitleRef->env_, subtitleRef->cb_, &jsCallback);
296              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
297                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
298  
299              // callback: (textInfo: TextInfoDescriptor)
300              napi_value args[1] = {nullptr};
301              napi_create_object(subtitleRef->env_, &args[0]);
302              (void)CommonNapi::SetPropertyString(subtitleRef->env_, args[0], "text", text);
303              napi_value result = nullptr;
304              status = napi_call_function(subtitleRef->env_, nullptr, jsCallback, 1, args, &result);
305              CHECK_AND_RETURN_LOG(status == napi_ok,
306                  "%{public}s fail to napi_call_function", callbackName.c_str());
307          }
308      };
309  
310      struct ObjectArray : public Base {
311          std::multimap<std::string, std::vector<uint8_t>> infoMap;
UvWorkOHOS::Media::NapiCallback::ObjectArray312          void UvWork() override
313          {
314              std::shared_ptr<AutoRef> mapRef = callback.lock();
315              CHECK_AND_RETURN_LOG(mapRef != nullptr,
316                  "%{public}s AutoRef is nullptr", callbackName.c_str());
317  
318              napi_handle_scope scope = nullptr;
319              napi_open_handle_scope(mapRef->env_, &scope);
320              CHECK_AND_RETURN_LOG(scope != nullptr,
321                  "%{public}s scope is nullptr", callbackName.c_str());
322              ON_SCOPE_EXIT(0) {
323                  napi_close_handle_scope(mapRef->env_, scope);
324              };
325  
326              napi_value jsCallback = nullptr;
327              napi_status status = napi_get_reference_value(mapRef->env_, mapRef->cb_, &jsCallback);
328              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
329                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
330  
331              uint32_t index = 0;
332              napi_value napiMap;
333              napi_create_array_with_length(mapRef->env_, infoMap.size(), &napiMap);
334              for (auto item : infoMap) {
335                  napi_value jsObject;
336                  napi_value jsUuid;
337                  napi_value jsPssh;
338                  napi_create_object(mapRef->env_, &jsObject);
339                  napi_create_string_utf8(mapRef->env_, item.first.c_str(), NAPI_AUTO_LENGTH, &jsUuid);
340                  napi_set_named_property(mapRef->env_, jsObject, "uuid", jsUuid);
341  
342                  status = napi_create_array_with_length(mapRef->env_, item.second.size(), &jsPssh);
343                  for (uint32_t i = 0; i < item.second.size(); i++) {
344                      napi_value number = nullptr;
345                      (void)napi_create_uint32(mapRef->env_, item.second[i], &number);
346                      (void)napi_set_element(mapRef->env_, jsPssh, i, number);
347                  }
348                  napi_set_named_property(mapRef->env_, jsObject, "pssh", jsPssh);
349                  napi_set_element(mapRef->env_, napiMap, index, jsObject);
350                  index++;
351              }
352  
353              const int32_t argCount = 1;
354              napi_value args[argCount] = { napiMap };
355              napi_value result = nullptr;
356              status = napi_call_function(mapRef->env_, nullptr, jsCallback, argCount, args, &result);
357              CHECK_AND_RETURN_LOG(status == napi_ok,
358                  "%{public}s failed to napi_call_function", callbackName.c_str());
359          }
360      };
361  
362      struct PropertyInt : public Base {
363          std::map<std::string, int32_t> valueMap;
UvWorkOHOS::Media::NapiCallback::PropertyInt364          void UvWork() override
365          {
366              std::shared_ptr<AutoRef> propertyIntRef = callback.lock();
367              CHECK_AND_RETURN_LOG(propertyIntRef != nullptr,
368                  "%{public}s AutoRef is nullptr", callbackName.c_str());
369  
370              napi_handle_scope scope = nullptr;
371              napi_open_handle_scope(propertyIntRef->env_, &scope);
372              CHECK_AND_RETURN_LOG(scope != nullptr,
373                  "%{public}s scope is nullptr", callbackName.c_str());
374              ON_SCOPE_EXIT(0) {
375                  napi_close_handle_scope(propertyIntRef->env_, scope);
376              };
377  
378              napi_value jsCallback = nullptr;
379              napi_status status = napi_get_reference_value(propertyIntRef->env_, propertyIntRef->cb_, &jsCallback);
380              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
381                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
382  
383              napi_value args[1] = {nullptr};
384              napi_create_object(propertyIntRef->env_, &args[0]);
385              for (auto &it : valueMap) {
386                  CommonNapi::SetPropertyInt32(propertyIntRef->env_, args[0], it.first, it.second);
387              }
388  
389              napi_value result = nullptr;
390              status = napi_call_function(propertyIntRef->env_, nullptr, jsCallback, 1, args, &result);
391              CHECK_AND_RETURN_LOG(status == napi_ok,
392                  "%{public}s fail to napi_call_function", callbackName.c_str());
393          }
394      };
395  
396      struct StateChange : public Base {
397          std::string state = "";
398          int32_t reason = 0;
UvWorkOHOS::Media::NapiCallback::StateChange399          void UvWork() override
400          {
401              std::shared_ptr<AutoRef> stateChangeRef = callback.lock();
402              CHECK_AND_RETURN_LOG(stateChangeRef != nullptr,
403                  "%{public}s AutoRef is nullptr", callbackName.c_str());
404  
405              napi_handle_scope scope = nullptr;
406              napi_open_handle_scope(stateChangeRef->env_, &scope);
407              CHECK_AND_RETURN_LOG(scope != nullptr,
408                  "%{public}s scope is nullptr", callbackName.c_str());
409              ON_SCOPE_EXIT(0) {
410                  napi_close_handle_scope(stateChangeRef->env_, scope);
411              };
412  
413              napi_value jsCallback = nullptr;
414              napi_status status = napi_get_reference_value(stateChangeRef->env_, stateChangeRef->cb_, &jsCallback);
415              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
416                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
417  
418              const int32_t argCount = 2;
419              // callback: (state: AVPlayerState, reason: StateChangeReason)
420              napi_value args[argCount] = {nullptr};
421              (void)napi_create_string_utf8(stateChangeRef->env_, state.c_str(), NAPI_AUTO_LENGTH, &args[0]);
422              (void)napi_create_int32(stateChangeRef->env_, reason, &args[1]);
423  
424              napi_value result = nullptr;
425              status = napi_call_function(stateChangeRef->env_, nullptr, jsCallback, argCount, args, &result);
426              CHECK_AND_RETURN_LOG(status == napi_ok,
427                  "%{public}s fail to napi_call_function", callbackName.c_str());
428          }
429      };
430  
CompleteCallback(napi_env env,NapiCallback::Base * jsCb)431      static void CompleteCallback(napi_env env, NapiCallback::Base *jsCb)
432      {
433          ON_SCOPE_EXIT(0) {
434              delete jsCb;
435          };
436  
437          if (jsCb != nullptr && jsCb->callbackName == AVPlayerEvent::EVENT_BUFFERING_UPDATE) {
438              napi_status ret = napi_send_event(env, [jsCb] () {
439                  CHECK_AND_RETURN_LOG(jsCb != nullptr, "Work thread is nullptr");
440                  MEDIA_LOGD("JsCallBack %{public}s start", jsCb->callbackName.c_str());
441                  jsCb->UvWork();
442                  delete jsCb;
443              }, napi_eprio_immediate);
444              if (ret != napi_ok) {
445                  MEDIA_LOGE("Failed to execute libuv work queue");
446                  delete jsCb;
447              }
448          } else {
449              uv_loop_s *loop = nullptr;
450              napi_get_uv_event_loop(env, &loop);
451              CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to napi_get_uv_event_loop");
452  
453              uv_work_t *work = new(std::nothrow) uv_work_t;
454              CHECK_AND_RETURN_LOG(work != nullptr, "Fail to new uv_work_t");
455  
456              work->data = reinterpret_cast<void *>(jsCb);
457              // async callback, jsWork and jsWork->data should be heap object.
458              int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
459                  CHECK_AND_RETURN_LOG(work != nullptr, "Work thread is nullptr");
460                  (void)status;
461                  NapiCallback::Base *cb = reinterpret_cast<NapiCallback::Base *>(work->data);
462                  if (cb != nullptr) {
463                      MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work_with_qos start", cb->callbackName.c_str());
464                      cb->UvWork();
465                      delete cb;
466                  }
467                  delete work;
468              }, uv_qos_user_initiated);
469              if (ret != 0) {
470                  MEDIA_LOGE("Failed to execute libuv work queue");
471                  delete jsCb;
472                  delete work;
473              }
474          }
475          CANCEL_SCOPE_EXIT_GUARD(0);
476      }
477  
478      struct TrackChange : public Base {
479          int32_t number = 0;
480          bool isSelect = false;
UvWorkOHOS::Media::NapiCallback::TrackChange481          void UvWork() override
482          {
483              std::shared_ptr<AutoRef> trackChangeRef = callback.lock();
484              CHECK_AND_RETURN_LOG(trackChangeRef != nullptr, "%{public}s AutoRef is nullptr", callbackName.c_str());
485  
486              napi_handle_scope scope = nullptr;
487              napi_open_handle_scope(trackChangeRef->env_, &scope);
488              CHECK_AND_RETURN_LOG(scope != nullptr, "%{public}s scope is nullptr", callbackName.c_str());
489              ON_SCOPE_EXIT(0) {
490                  napi_close_handle_scope(trackChangeRef->env_, scope);
491              };
492  
493              napi_value jsCallback = nullptr;
494              napi_status status = napi_get_reference_value(trackChangeRef->env_, trackChangeRef->cb_, &jsCallback);
495              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
496                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
497  
498              const int32_t argCount = 2; // 2 prapm, callback: (index: number, isSelect: boolean)
499              napi_value args[argCount] = {nullptr};
500              (void)napi_create_int32(trackChangeRef->env_, number, &args[0]);
501              (void)napi_get_boolean(trackChangeRef->env_, isSelect, &args[1]);
502  
503              napi_value result = nullptr;
504              status = napi_call_function(trackChangeRef->env_, nullptr, jsCallback, argCount, args, &result);
505              CHECK_AND_RETURN_LOG(status == napi_ok, "%{public}s fail to napi_call_function", callbackName.c_str());
506          }
507      };
508  
509      struct SubtitleInfo : public Base {
510          struct SubtitleParam {
511              std::string text;
512              int32_t pts;
513              int32_t duration;
514          } valueMap;
UvWorkOHOS::Media::NapiCallback::SubtitleInfo515          void UvWork() override
516          {
517              std::shared_ptr<AutoRef> subtitleRef = callback.lock();
518              CHECK_AND_RETURN_LOG(subtitleRef != nullptr, "%{public}s AutoRef is nullptr", callbackName.c_str());
519  
520              napi_handle_scope scope = nullptr;
521              napi_open_handle_scope(subtitleRef->env_, &scope);
522              CHECK_AND_RETURN_LOG(scope != nullptr, "%{public}s scope is nullptr", callbackName.c_str());
523              ON_SCOPE_EXIT(0) {
524                  napi_close_handle_scope(subtitleRef->env_, scope);
525              };
526  
527              napi_value jsCallback = nullptr;
528              napi_status status = napi_get_reference_value(subtitleRef->env_, subtitleRef->cb_, &jsCallback);
529              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
530                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
531  
532              napi_value args[1] = {nullptr};
533              napi_create_object(subtitleRef->env_, &args[0]);
534              CommonNapi::SetPropertyString(subtitleRef->env_, args[0], "text", valueMap.text);
535              CommonNapi::SetPropertyInt32(subtitleRef->env_, args[0], "startTime", valueMap.pts);
536              CommonNapi::SetPropertyInt32(subtitleRef->env_, args[0], "duration", valueMap.duration);
537              napi_value result = nullptr;
538              status = napi_call_function(subtitleRef->env_, nullptr, jsCallback, 1, args, &result);
539              CHECK_AND_RETURN_LOG(status == napi_ok, "%{public}s fail to napi_call_function", callbackName.c_str());
540          }
541      };
542  
543      struct DeviceChangeNapi : public Base {
544          AudioStandard::DeviceInfo deviceInfo;
545          int32_t reason;
UvWorkOHOS::Media::NapiCallback::DeviceChangeNapi546          void UvWork() override
547          {
548              std::shared_ptr<AutoRef> deviceChangeRef = callback.lock();
549              CHECK_AND_RETURN_LOG(deviceChangeRef != nullptr, "%{public}s AutoRef is nullptr", callbackName.c_str());
550  
551              napi_handle_scope scope = nullptr;
552              napi_open_handle_scope(deviceChangeRef->env_, &scope);
553              CHECK_AND_RETURN_LOG(scope != nullptr, "%{public}s scope is nullptr", callbackName.c_str());
554              ON_SCOPE_EXIT(0) {
555                  napi_close_handle_scope(deviceChangeRef->env_, scope);
556              };
557  
558              napi_value jsCallback = nullptr;
559              napi_status status = napi_get_reference_value(deviceChangeRef->env_, deviceChangeRef->cb_, &jsCallback);
560              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
561                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
562  
563              constexpr size_t argCount = 1;
564              napi_value args[argCount] = {};
565              napi_create_object(deviceChangeRef->env_, &args[0]);
566              napi_value deviceObj = nullptr;
567              status = CommonNapi::SetValueDeviceInfo(deviceChangeRef->env_, deviceInfo, deviceObj);
568              CHECK_AND_RETURN_LOG(status == napi_ok && deviceObj != nullptr,
569                  " fail to convert to jsobj");
570              napi_set_named_property(deviceChangeRef->env_, args[0], "devices", deviceObj);
571  
572              bool res = CommonNapi::SetPropertyInt32(deviceChangeRef->env_, args[0], "changeReason",
573                  static_cast<const int32_t> (reason));
574              CHECK_AND_RETURN_LOG(res && deviceObj != nullptr,
575                  " fail to convert to jsobj");
576  
577              napi_value result = nullptr;
578              status = napi_call_function(deviceChangeRef->env_, nullptr, jsCallback, argCount, args, &result);
579              CHECK_AND_RETURN_LOG(status == napi_ok, "%{public}s fail to napi_call_function", callbackName.c_str());
580          }
581      };
582  
583      struct TrackInfoUpdate : public Base {
584          std::vector<Format> trackInfo;
UvWorkOHOS::Media::NapiCallback::TrackInfoUpdate585          void UvWork() override
586          {
587              std::shared_ptr<AutoRef> trackInfoRef = callback.lock();
588              CHECK_AND_RETURN_LOG(trackInfoRef != nullptr, "%{public}s AutoRef is nullptr", callbackName.c_str());
589  
590              napi_handle_scope scope = nullptr;
591              napi_open_handle_scope(trackInfoRef->env_, &scope);
592              CHECK_AND_RETURN_LOG(scope != nullptr, "%{public}s scope is nullptr", callbackName.c_str());
593              ON_SCOPE_EXIT(0) {
594                  napi_close_handle_scope(trackInfoRef->env_, scope);
595              };
596  
597              napi_value jsCallback = nullptr;
598              napi_status status = napi_get_reference_value(trackInfoRef->env_, trackInfoRef->cb_, &jsCallback);
599              CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
600                  "%{public}s failed to napi_get_reference_value", callbackName.c_str());
601  
602              napi_value array = nullptr;
603              (void)napi_create_array_with_length(trackInfoRef->env_, trackInfo.size(), &array);
604  
605              for (uint32_t i = 0; i < trackInfo.size(); i++) {
606                  napi_value trackDescription = nullptr;
607                  trackDescription = CommonNapi::CreateFormatBuffer(trackInfoRef->env_, trackInfo[i]);
608                  (void)napi_set_element(trackInfoRef->env_, array, i, trackDescription);
609              }
610  
611              napi_value result = nullptr;
612              napi_value args[1] = {array};
613              status = napi_call_function(trackInfoRef->env_, nullptr, jsCallback, 1, args, &result);
614              CHECK_AND_RETURN_LOG(status == napi_ok,
615                  "%{public}s failed to napi_call_function", callbackName.c_str());
616          }
617      };
618  };
619  
AVPlayerCallback(napi_env env,AVPlayerNotify * listener)620  AVPlayerCallback::AVPlayerCallback(napi_env env, AVPlayerNotify *listener)
621      : env_(env), listener_(listener)
622  {
623      MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
624      onInfoFuncs_ = {
625          { INFO_TYPE_STATE_CHANGE,
626              [this](const int32_t extra, const Format &infoBody) { OnStateChangeCb(extra, infoBody); } },
627          { INFO_TYPE_VOLUME_CHANGE,
628              [this](const int32_t extra, const Format &infoBody) { OnVolumeChangeCb(extra, infoBody); } },
629          { INFO_TYPE_SEEKDONE,
630              [this](const int32_t extra, const Format &infoBody) { OnSeekDoneCb(extra, infoBody); } },
631          { INFO_TYPE_SPEEDDONE,
632              [this](const int32_t extra, const Format &infoBody) { OnSpeedDoneCb(extra, infoBody); } },
633          { INFO_TYPE_BITRATEDONE,
634              [this](const int32_t extra, const Format &infoBody) { OnBitRateDoneCb(extra, infoBody); } },
635          { INFO_TYPE_POSITION_UPDATE,
636              [this](const int32_t extra, const Format &infoBody) { OnPositionUpdateCb(extra, infoBody); } },
637          { INFO_TYPE_DURATION_UPDATE,
638              [this](const int32_t extra, const Format &infoBody) { OnDurationUpdateCb(extra, infoBody); } },
639          { INFO_TYPE_BUFFERING_UPDATE,
640              [this](const int32_t extra, const Format &infoBody) { OnBufferingUpdateCb(extra, infoBody); } },
641          { INFO_TYPE_MESSAGE,
642              [this](const int32_t extra, const Format &infoBody) { OnMessageCb(extra, infoBody);} },
643          { INFO_TYPE_RESOLUTION_CHANGE,
644              [this](const int32_t extra, const Format &infoBody) { OnVideoSizeChangedCb(extra, infoBody); } },
645          { INFO_TYPE_INTERRUPT_EVENT,
646              [this](const int32_t extra, const Format &infoBody) { OnAudioInterruptCb(extra, infoBody); } },
647          { INFO_TYPE_BITRATE_COLLECT,
648               [this](const int32_t extra, const Format &infoBody) { OnBitRateCollectedCb(extra, infoBody); } },
649          { INFO_TYPE_EOS,
650              [this](const int32_t extra, const Format &infoBody) { OnEosCb(extra, infoBody); } },
651          { INFO_TYPE_IS_LIVE_STREAM,
652              [this](const int32_t extra, const Format &infoBody) { NotifyIsLiveStream(extra, infoBody); } },
653          { INFO_TYPE_SUBTITLE_UPDATE,
654              [this](const int32_t extra, const Format &infoBody) { OnSubtitleUpdateCb(extra, infoBody); } },
655          { INFO_TYPE_TRACKCHANGE,
656              [this](const int32_t extra, const Format &infoBody) { OnTrackChangedCb(extra, infoBody); } },
657          { INFO_TYPE_TRACK_INFO_UPDATE,
658              [this](const int32_t extra, const Format &infoBody) { OnTrackInfoUpdate(extra, infoBody); } },
659          { INFO_TYPE_DRM_INFO_UPDATED,
660              [this](const int32_t extra, const Format &infoBody) { OnDrmInfoUpdatedCb(extra, infoBody); } },
661          { INFO_TYPE_SET_DECRYPT_CONFIG_DONE,
662              [this](const int32_t extra, const Format &infoBody) { OnSetDecryptConfigDoneCb(extra, infoBody); } },
663          { INFO_TYPE_SUBTITLE_UPDATE_INFO,
664              [this](const int32_t extra, const Format &infoBody) { OnSubtitleInfoCb(extra, infoBody); } },
665          { INFO_TYPE_AUDIO_DEVICE_CHANGE,
666              [this](const int32_t extra, const Format &infoBody) { OnAudioDeviceChangeCb(extra, infoBody); } },
667          { INFO_TYPE_MAX_AMPLITUDE_COLLECT,
668               [this](const int32_t extra, const Format &infoBody) { OnMaxAmplitudeCollectedCb(extra, infoBody); } },
669      };
670  }
671  
OnAudioDeviceChangeCb(const int32_t extra,const Format & infoBody)672  void AVPlayerCallback::OnAudioDeviceChangeCb(const int32_t extra, const Format &infoBody)
673  {
674      (void)extra;
675      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
676      if (refMap_.find(AVPlayerEvent::EVENT_AUDIO_DEVICE_CHANGE) == refMap_.end()) {
677          MEDIA_LOGD("0x%{public}06" PRIXPTR " can not find audio AudioDeviceChange callback!", FAKE_POINTER(this));
678          return;
679      }
680  
681      NapiCallback::DeviceChangeNapi *cb = new(std::nothrow) NapiCallback::DeviceChangeNapi();
682      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new DeviceChangeNapi");
683  
684      cb->callback = refMap_.at(AVPlayerEvent::EVENT_AUDIO_DEVICE_CHANGE);
685      cb->callbackName = AVPlayerEvent::EVENT_AUDIO_DEVICE_CHANGE;
686  
687      uint8_t *parcelBuffer = nullptr;
688      size_t parcelSize;
689      infoBody.GetBuffer(PlayerKeys::AUDIO_DEVICE_CHANGE, &parcelBuffer, parcelSize);
690      Parcel parcel;
691      parcel.WriteBuffer(parcelBuffer, parcelSize);
692      AudioStandard::DeviceInfo deviceInfo;
693      deviceInfo.Unmarshalling(parcel);
694  
695      int32_t reason;
696      infoBody.GetIntValue(PlayerKeys::AUDIO_DEVICE_CHANGE_REASON, reason);
697  
698      cb->deviceInfo = deviceInfo;
699      cb->reason = reason;
700  
701      NapiCallback::CompleteCallback(env_, cb);
702  }
703  
~AVPlayerCallback()704  AVPlayerCallback::~AVPlayerCallback()
705  {
706      MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
707  }
708  
OnError(int32_t errorCode,const std::string & errorMsg)709  void AVPlayerCallback::OnError(int32_t errorCode, const std::string &errorMsg)
710  {
711      MediaServiceExtErrCodeAPI9 errorCodeApi9 = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errorCode));
712      if (errorCodeApi9 == MSERR_EXT_API9_NO_PERMISSION ||
713          errorCodeApi9 == MSERR_EXT_API9_NO_MEMORY ||
714          errorCodeApi9 == MSERR_EXT_API9_TIMEOUT ||
715          errorCodeApi9 == MSERR_EXT_API9_SERVICE_DIED ||
716          errorCodeApi9 == MSERR_EXT_API9_UNSUPPORT_FORMAT) {
717          Format infoBody;
718          AVPlayerCallback::OnInfo(INFO_TYPE_STATE_CHANGE, PLAYER_STATE_ERROR, infoBody);
719      }
720      AVPlayerCallback::OnErrorCb(errorCodeApi9, errorMsg);
721  }
722  
OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode,const std::string & errorMsg)723  void AVPlayerCallback::OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg)
724  {
725      std::string message = MSExtAVErrorToString(errorCode) + errorMsg;
726      MEDIA_LOGE("OnErrorCb:errorCode %{public}d, errorMsg %{public}s", errorCode, message.c_str());
727      std::lock_guard<std::mutex> lock(mutex_);
728      if (refMap_.find(AVPlayerEvent::EVENT_ERROR) == refMap_.end()) {
729          MEDIA_LOGW("0x%{public}06" PRIXPTR " can not find error callback!", FAKE_POINTER(this));
730          return;
731      }
732  
733      NapiCallback::Error *cb = new(std::nothrow) NapiCallback::Error();
734      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Error");
735  
736      cb->callback = refMap_.at(AVPlayerEvent::EVENT_ERROR);
737      cb->callbackName = AVPlayerEvent::EVENT_ERROR;
738      cb->errorCode = errorCode;
739      cb->errorMsg = message;
740      NapiCallback::CompleteCallback(env_, cb);
741  }
742  
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)743  void AVPlayerCallback::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
744  {
745      std::lock_guard<std::mutex> lock(mutex_);
746      MEDIA_LOGD("OnInfo is called, PlayerOnInfoType: %{public}d", type);
747      if (onInfoFuncs_.count(type) > 0) {
748          onInfoFuncs_[type](extra, infoBody);
749      } else {
750          MEDIA_LOGD("0x%{public}06" PRIXPTR " OnInfo: no member func supporting, %{public}d",
751              FAKE_POINTER(this), type);
752      }
753  }
754  
NotifyIsLiveStream(const int32_t extra,const Format & infoBody)755  void AVPlayerCallback::NotifyIsLiveStream(const int32_t extra, const Format &infoBody)
756  {
757      (void)extra;
758      (void)infoBody;
759      if (listener_ != nullptr) {
760          listener_->NotifyIsLiveStream();
761      }
762  }
763  
IsValidState(PlayerStates state,std::string & stateStr)764  bool AVPlayerCallback::IsValidState(PlayerStates state, std::string &stateStr)
765  {
766      switch (state) {
767          case PlayerStates::PLAYER_IDLE:
768              stateStr = AVPlayerState::STATE_IDLE;
769              break;
770          case PlayerStates::PLAYER_INITIALIZED:
771              stateStr = AVPlayerState::STATE_INITIALIZED;
772              break;
773          case PlayerStates::PLAYER_PREPARED:
774              stateStr = AVPlayerState::STATE_PREPARED;
775              break;
776          case PlayerStates::PLAYER_STARTED:
777              stateStr = AVPlayerState::STATE_PLAYING;
778              break;
779          case PlayerStates::PLAYER_PAUSED:
780              stateStr = AVPlayerState::STATE_PAUSED;
781              break;
782          case PlayerStates::PLAYER_STOPPED:
783              stateStr = AVPlayerState::STATE_STOPPED;
784              break;
785          case PlayerStates::PLAYER_PLAYBACK_COMPLETE:
786              stateStr = AVPlayerState::STATE_COMPLETED;
787              break;
788          case PlayerStates::PLAYER_RELEASED:
789              stateStr = AVPlayerState::STATE_RELEASED;
790              break;
791          case PlayerStates::PLAYER_STATE_ERROR:
792              stateStr = AVPlayerState::STATE_ERROR;
793              break;
794          default:
795              return false;
796      }
797      return true;
798  }
799  
OnStateChangeCb(const int32_t extra,const Format & infoBody)800  void AVPlayerCallback::OnStateChangeCb(const int32_t extra, const Format &infoBody)
801  {
802      PlayerStates state = static_cast<PlayerStates>(extra);
803      MEDIA_LOGI("0x%{public}06" PRIXPTR " Instance OnStateChanged is called, current state: %{public}d",
804          FAKE_POINTER(this), state);
805  
806      if (listener_ != nullptr) {
807          listener_->NotifyState(state);
808      }
809  
810      if (state_ != state) {
811          state_ = state;
812          std::string stateStr;
813          if (IsValidState(state, stateStr)) {
814              if (refMap_.find(AVPlayerEvent::EVENT_STATE_CHANGE) == refMap_.end()) {
815                  MEDIA_LOGW("can not find state change callback!");
816                  return;
817              }
818              NapiCallback::StateChange *cb = new(std::nothrow) NapiCallback::StateChange();
819              CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new StateChange");
820  
821              int32_t reason = StateChangeReason::USER;
822              if (infoBody.ContainKey(PlayerKeys::PLAYER_STATE_CHANGED_REASON)) {
823                  (void)infoBody.GetIntValue(PlayerKeys::PLAYER_STATE_CHANGED_REASON, reason);
824              }
825              cb->callback = refMap_.at(AVPlayerEvent::EVENT_STATE_CHANGE);
826              cb->callbackName = AVPlayerEvent::EVENT_STATE_CHANGE;
827              cb->state = stateStr;
828              cb->reason = reason;
829              NapiCallback::CompleteCallback(env_, cb);
830          }
831      }
832  }
833  
OnVolumeChangeCb(const int32_t extra,const Format & infoBody)834  void AVPlayerCallback::OnVolumeChangeCb(const int32_t extra, const Format &infoBody)
835  {
836      (void)extra;
837      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
838      float volumeLevel = 0.0;
839      (void)infoBody.GetFloatValue(PlayerKeys::PLAYER_VOLUME_LEVEL, volumeLevel);
840  
841      isSetVolume_ = false;
842      MEDIA_LOGD("OnVolumeChangeCb in volume=%{public}f", volumeLevel);
843      if (refMap_.find(AVPlayerEvent::EVENT_VOLUME_CHANGE) == refMap_.end()) {
844          MEDIA_LOGD("can not find vol change callback!");
845          return;
846      }
847  
848      NapiCallback::Double *cb = new(std::nothrow) NapiCallback::Double();
849      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Double");
850      cb->callback = refMap_.at(AVPlayerEvent::EVENT_VOLUME_CHANGE);
851      cb->callbackName = AVPlayerEvent::EVENT_VOLUME_CHANGE;
852      cb->value = static_cast<double>(volumeLevel);
853      NapiCallback::CompleteCallback(env_, cb);
854  }
855  
OnSeekDoneCb(const int32_t extra,const Format & infoBody)856  void AVPlayerCallback::OnSeekDoneCb(const int32_t extra, const Format &infoBody)
857  {
858      (void)infoBody;
859      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
860      int32_t currentPositon = extra;
861      MEDIA_LOGI("0x%{public}06" PRIXPTR " OnSeekDone is called, currentPositon: %{public}d",
862          FAKE_POINTER(this), currentPositon);
863      if (refMap_.find(AVPlayerEvent::EVENT_SEEK_DONE) == refMap_.end()) {
864          MEDIA_LOGW("0x%{public}06" PRIXPTR " can not find seekdone callback!", FAKE_POINTER(this));
865          return;
866      }
867      NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
868      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
869  
870      cb->callback = refMap_.at(AVPlayerEvent::EVENT_SEEK_DONE);
871      cb->callbackName = AVPlayerEvent::EVENT_SEEK_DONE;
872      cb->value = currentPositon;
873      NapiCallback::CompleteCallback(env_, cb);
874  }
875  
OnSpeedDoneCb(const int32_t extra,const Format & infoBody)876  void AVPlayerCallback::OnSpeedDoneCb(const int32_t extra, const Format &infoBody)
877  {
878      (void)infoBody;
879      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
880      int32_t speedMode = extra;
881      MEDIA_LOGI("OnSpeedDoneCb is called, speedMode: %{public}d", speedMode);
882      if (refMap_.find(AVPlayerEvent::EVENT_SPEED_DONE) == refMap_.end()) {
883          MEDIA_LOGW("can not find speeddone callback!");
884          return;
885      }
886  
887      NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
888      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
889  
890      cb->callback = refMap_.at(AVPlayerEvent::EVENT_SPEED_DONE);
891      cb->callbackName = AVPlayerEvent::EVENT_SPEED_DONE;
892      cb->value = speedMode;
893      NapiCallback::CompleteCallback(env_, cb);
894  }
895  
OnBitRateDoneCb(const int32_t extra,const Format & infoBody)896  void AVPlayerCallback::OnBitRateDoneCb(const int32_t extra, const Format &infoBody)
897  {
898      (void)infoBody;
899      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
900      int32_t bitRate = extra;
901      MEDIA_LOGI("OnBitRateDoneCb is called, bitRate: %{public}d", bitRate);
902      if (refMap_.find(AVPlayerEvent::EVENT_BITRATE_DONE) == refMap_.end()) {
903          MEDIA_LOGW("can not find bitrate callback!");
904          return;
905      }
906  
907      NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
908      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
909  
910      cb->callback = refMap_.at(AVPlayerEvent::EVENT_BITRATE_DONE);
911      cb->callbackName = AVPlayerEvent::EVENT_BITRATE_DONE;
912      cb->value = bitRate;
913      NapiCallback::CompleteCallback(env_, cb);
914  }
915  
OnPositionUpdateCb(const int32_t extra,const Format & infoBody)916  void AVPlayerCallback::OnPositionUpdateCb(const int32_t extra, const Format &infoBody)
917  {
918      (void)infoBody;
919      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
920      int32_t position = extra;
921      MEDIA_LOGD("OnPositionUpdateCb is called, position: %{public}d", position);
922  
923      if (listener_ != nullptr) {
924          listener_->NotifyPosition(position);
925      }
926  
927      if (refMap_.find(AVPlayerEvent::EVENT_TIME_UPDATE) == refMap_.end()) {
928          MEDIA_LOGD("can not find timeupdate callback!");
929          return;
930      }
931      NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
932      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
933  
934      cb->callback = refMap_.at(AVPlayerEvent::EVENT_TIME_UPDATE);
935      cb->callbackName = AVPlayerEvent::EVENT_TIME_UPDATE;
936      cb->value = position;
937      NapiCallback::CompleteCallback(env_, cb);
938  }
939  
OnDurationUpdateCb(const int32_t extra,const Format & infoBody)940  void AVPlayerCallback::OnDurationUpdateCb(const int32_t extra, const Format &infoBody)
941  {
942      (void)infoBody;
943      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
944      int32_t duration = extra;
945      MEDIA_LOGI("0x%{public}06" PRIXPTR " OnDurationUpdateCb is called, duration: %{public}d",
946          FAKE_POINTER(this), duration);
947  
948      if (listener_ != nullptr) {
949          listener_->NotifyDuration(duration);
950      }
951  
952      if (refMap_.find(AVPlayerEvent::EVENT_DURATION_UPDATE) == refMap_.end()) {
953          MEDIA_LOGD("0x%{public}06" PRIXPTR " can not find duration update callback!", FAKE_POINTER(this));
954          return;
955      }
956  
957      NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
958      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
959  
960      cb->callback = refMap_.at(AVPlayerEvent::EVENT_DURATION_UPDATE);
961      cb->callbackName = AVPlayerEvent::EVENT_DURATION_UPDATE;
962      cb->value = duration;
963      NapiCallback::CompleteCallback(env_, cb);
964  }
965  
OnSubtitleUpdateCb(const int32_t extra,const Format & infoBody)966  void AVPlayerCallback::OnSubtitleUpdateCb(const int32_t extra, const Format &infoBody)
967  {
968      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
969      if (refMap_.find(AVPlayerEvent::EVENT_SUBTITLE_TEXT_UPDATE) == refMap_.end()) {
970          MEDIA_LOGW("can not find subtitle update callback!");
971          return;
972      }
973      NapiCallback::SubtitleProperty *cb = new(std::nothrow) NapiCallback::SubtitleProperty();
974      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new SubtitleProperty");
975      if (infoBody.ContainKey(PlayerKeys::SUBTITLE_TEXT)) {
976          (void)infoBody.GetStringValue(PlayerKeys::SUBTITLE_TEXT, cb->text);
977      }
978      cb->callback = refMap_.at(AVPlayerEvent::EVENT_SUBTITLE_TEXT_UPDATE);
979      cb->callbackName = AVPlayerEvent::EVENT_SUBTITLE_TEXT_UPDATE;
980      NapiCallback::CompleteCallback(env_, cb);
981  }
982  
OnBufferingUpdateCb(const int32_t extra,const Format & infoBody)983  void AVPlayerCallback::OnBufferingUpdateCb(const int32_t extra, const Format &infoBody)
984  {
985      (void)extra;
986      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
987      if (refMap_.find(AVPlayerEvent::EVENT_BUFFERING_UPDATE) == refMap_.end()) {
988          MEDIA_LOGD("can not find buffering update callback!");
989          return;
990      }
991  
992      int32_t val = 0;
993      int32_t bufferingType = -1;
994      if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_START))) {
995          bufferingType = BUFFERING_START;
996          (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_START), val);
997      } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_END))) {
998          bufferingType = BUFFERING_END;
999          (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_END), val);
1000      } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT))) {
1001          bufferingType = BUFFERING_PERCENT;
1002          (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), val);
1003      } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_CACHED_DURATION))) {
1004          bufferingType = CACHED_DURATION;
1005          (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION), val);
1006      } else {
1007          return;
1008      }
1009  
1010      MEDIA_LOGD("OnBufferingUpdateCb is called, buffering type: %{public}d value: %{public}d", bufferingType, val);
1011      NapiCallback::IntVec *cb = new(std::nothrow) NapiCallback::IntVec();
1012      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntVec");
1013  
1014      cb->callback = refMap_.at(AVPlayerEvent::EVENT_BUFFERING_UPDATE);
1015      cb->callbackName = AVPlayerEvent::EVENT_BUFFERING_UPDATE;
1016      cb->valueVec.push_back(bufferingType);
1017      cb->valueVec.push_back(val);
1018      NapiCallback::CompleteCallback(env_, cb);
1019  }
1020  
OnMessageCb(const int32_t extra,const Format & infoBody)1021  void AVPlayerCallback::OnMessageCb(const int32_t extra, const Format &infoBody)
1022  {
1023      (void)infoBody;
1024      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1025      MEDIA_LOGI("OnMessageCb is called, extra: %{public}d", extra);
1026      if (extra == PlayerMessageType::PLAYER_INFO_VIDEO_RENDERING_START) {
1027          AVPlayerCallback::OnStartRenderFrameCb();
1028      }
1029  }
1030  
OnStartRenderFrameCb() const1031  void AVPlayerCallback::OnStartRenderFrameCb() const
1032  {
1033      MEDIA_LOGI("OnStartRenderFrameCb is called");
1034      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1035      if (refMap_.find(AVPlayerEvent::EVENT_START_RENDER_FRAME) == refMap_.end()) {
1036          MEDIA_LOGW("can not find start render callback!");
1037          return;
1038      }
1039  
1040      NapiCallback::Base *cb = new(std::nothrow) NapiCallback::Base();
1041      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Base");
1042  
1043      cb->callback = refMap_.at(AVPlayerEvent::EVENT_START_RENDER_FRAME);
1044      cb->callbackName = AVPlayerEvent::EVENT_START_RENDER_FRAME;
1045      NapiCallback::CompleteCallback(env_, cb);
1046  }
1047  
OnVideoSizeChangedCb(const int32_t extra,const Format & infoBody)1048  void AVPlayerCallback::OnVideoSizeChangedCb(const int32_t extra, const Format &infoBody)
1049  {
1050      (void)extra;
1051      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1052      int32_t width = 0;
1053      int32_t height = 0;
1054      (void)infoBody.GetIntValue(PlayerKeys::PLAYER_WIDTH, width);
1055      (void)infoBody.GetIntValue(PlayerKeys::PLAYER_HEIGHT, height);
1056      MEDIA_LOGI("0x%{public}06" PRIXPTR " OnVideoSizeChangedCb is called, width = %{public}d, height = %{public}d",
1057          FAKE_POINTER(this), width, height);
1058  
1059      if (listener_ != nullptr) {
1060          listener_->NotifyVideoSize(width, height);
1061      }
1062  
1063      if (refMap_.find(AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE) == refMap_.end()) {
1064          MEDIA_LOGW("can not find video size changed callback!");
1065          return;
1066      }
1067      NapiCallback::IntVec *cb = new(std::nothrow) NapiCallback::IntVec();
1068      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntVec");
1069  
1070      cb->callback = refMap_.at(AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE);
1071      cb->callbackName = AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE;
1072      cb->valueVec.push_back(width);
1073      cb->valueVec.push_back(height);
1074      NapiCallback::CompleteCallback(env_, cb);
1075  }
1076  
OnAudioInterruptCb(const int32_t extra,const Format & infoBody)1077  void AVPlayerCallback::OnAudioInterruptCb(const int32_t extra, const Format &infoBody)
1078  {
1079      (void)extra;
1080      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1081      if (refMap_.find(AVPlayerEvent::EVENT_AUDIO_INTERRUPT) == refMap_.end()) {
1082          MEDIA_LOGW("can not find audio interrupt callback!");
1083          return;
1084      }
1085  
1086      NapiCallback::PropertyInt *cb = new(std::nothrow) NapiCallback::PropertyInt();
1087      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new PropertyInt");
1088  
1089      cb->callback = refMap_.at(AVPlayerEvent::EVENT_AUDIO_INTERRUPT);
1090      cb->callbackName = AVPlayerEvent::EVENT_AUDIO_INTERRUPT;
1091      int32_t eventType = 0;
1092      int32_t forceType = 0;
1093      int32_t hintType = 0;
1094      (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
1095      (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
1096      (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
1097      MEDIA_LOGI("OnAudioInterruptCb is called, eventType = %{public}d, forceType = %{public}d, hintType = %{public}d",
1098          eventType, forceType, hintType);
1099      // ohos.multimedia.audio.d.ts interface InterruptEvent
1100      cb->valueMap["eventType"] = eventType;
1101      cb->valueMap["forceType"] = forceType;
1102      cb->valueMap["hintType"] = hintType;
1103      NapiCallback::CompleteCallback(env_, cb);
1104  }
1105  
OnBitRateCollectedCb(const int32_t extra,const Format & infoBody)1106  void AVPlayerCallback::OnBitRateCollectedCb(const int32_t extra, const Format &infoBody)
1107  {
1108      (void)extra;
1109      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1110      if (refMap_.find(AVPlayerEvent::EVENT_AVAILABLE_BITRATES) == refMap_.end()) {
1111          MEDIA_LOGW("can not find bitrate collected callback!");
1112          return;
1113      }
1114  
1115      std::vector<int32_t> bitrateVec;
1116      if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_AVAILABLE_BITRATES))) {
1117          uint8_t *addr = nullptr;
1118          size_t size  = 0;
1119          infoBody.GetBuffer(std::string(PlayerKeys::PLAYER_AVAILABLE_BITRATES), &addr, size);
1120          CHECK_AND_RETURN_LOG(addr != nullptr, "bitrate addr is nullptr");
1121  
1122          MEDIA_LOGI("bitrate size = %{public}zu", size / sizeof(uint32_t));
1123          while (size > 0) {
1124              if (size < sizeof(uint32_t)) {
1125                  break;
1126              }
1127  
1128              uint32_t bitrate = *(static_cast<uint32_t *>(static_cast<void *>(addr)));
1129              MEDIA_LOGI("bitrate = %{public}u", bitrate);
1130              addr += sizeof(uint32_t);
1131              size -= sizeof(uint32_t);
1132              bitrateVec.push_back(static_cast<int32_t>(bitrate));
1133          }
1134      }
1135  
1136      NapiCallback::IntArray *cb = new(std::nothrow) NapiCallback::IntArray();
1137      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntArray");
1138  
1139      cb->callback = refMap_.at(AVPlayerEvent::EVENT_AVAILABLE_BITRATES);
1140      cb->callbackName = AVPlayerEvent::EVENT_AVAILABLE_BITRATES;
1141      cb->valueVec = bitrateVec;
1142      NapiCallback::CompleteCallback(env_, cb);
1143  }
1144  
OnMaxAmplitudeCollectedCb(const int32_t extra,const Format & infoBody)1145  void AVPlayerCallback::OnMaxAmplitudeCollectedCb(const int32_t extra, const Format &infoBody)
1146  {
1147      (void)extra;
1148      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1149      if (refMap_.find(AVPlayerEvent::EVENT_AMPLITUDE_UPDATE) == refMap_.end()) {
1150          MEDIA_LOGD("can not find max amplitude collected callback!");
1151          return;
1152      }
1153  
1154      std::vector<float> MaxAmplitudeVec;
1155      if (infoBody.ContainKey(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE))) {
1156          uint8_t *addr = nullptr;
1157          size_t size  = 0;
1158          infoBody.GetBuffer(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE), &addr, size);
1159          CHECK_AND_RETURN_LOG(addr != nullptr, "max amplitude addr is nullptr");
1160  
1161          MEDIA_LOGD("max amplitude size = %{public}zu", size / sizeof(float));
1162          while (size > 0) {
1163              if (size < sizeof(float)) {
1164                  break;
1165              }
1166  
1167              float maxAmplitude = *(static_cast<float *>(static_cast<void *>(addr)));
1168              MEDIA_LOGD("maxAmplitude = %{public}f", maxAmplitude);
1169              addr += sizeof(float);
1170              size -= sizeof(float);
1171              MaxAmplitudeVec.push_back(static_cast<float>(maxAmplitude));
1172          }
1173      }
1174  
1175      NapiCallback::FloatArray *cb = new(std::nothrow) NapiCallback::FloatArray();
1176      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntArray");
1177  
1178      cb->callback = refMap_.at(AVPlayerEvent::EVENT_AMPLITUDE_UPDATE);
1179      cb->callbackName = AVPlayerEvent::EVENT_AMPLITUDE_UPDATE;
1180      cb->valueVec = MaxAmplitudeVec;
1181      NapiCallback::CompleteCallback(env_, cb);
1182  }
1183  
SetDrmInfoData(const uint8_t * drmInfoAddr,int32_t infoCount,std::multimap<std::string,std::vector<uint8_t>> & drmInfoMap)1184  int32_t AVPlayerCallback::SetDrmInfoData(const uint8_t *drmInfoAddr, int32_t infoCount,
1185      std::multimap<std::string, std::vector<uint8_t>> &drmInfoMap)
1186  {
1187      DrmInfoItem *drmInfos = reinterpret_cast<DrmInfoItem*>(const_cast<uint8_t *>(drmInfoAddr));
1188      CHECK_AND_RETURN_RET_LOG(drmInfos != nullptr, MSERR_INVALID_VAL, "cast drmInfos nullptr");
1189      for (int32_t i = 0; i < infoCount; i++) {
1190          DrmInfoItem temp = drmInfos[i];
1191          std::stringstream ssConverter;
1192          std::string uuid;
1193          for (uint32_t index = 0; index < DrmConstant::DRM_MAX_M3U8_DRM_UUID_LEN; index++) {
1194              int32_t singleUuid = static_cast<int32_t>(temp.uuid[index]);
1195              ssConverter << std::hex << std::setfill('0') << std::setw(2) << singleUuid; // 2:w
1196              uuid = ssConverter.str();
1197          }
1198          std::vector<uint8_t> pssh(temp.pssh, temp.pssh + temp.psshLen);
1199          drmInfoMap.insert({ uuid, pssh });
1200      }
1201  
1202      if (listener_ != nullptr) {
1203          listener_->NotifyDrmInfoUpdated(drmInfoMap);
1204      }
1205      return MSERR_OK;
1206  }
1207  
OnDrmInfoUpdatedCb(const int32_t extra,const Format & infoBody)1208  void AVPlayerCallback::OnDrmInfoUpdatedCb(const int32_t extra, const Format &infoBody)
1209  {
1210      (void)extra;
1211      MEDIA_LOGI("AVPlayerCallback OnDrmInfoUpdatedCb is called");
1212      if (refMap_.find(AVPlayerEvent::EVENT_DRM_INFO_UPDATE) == refMap_.end()) {
1213          MEDIA_LOGW("can not find drm info updated callback!");
1214          return;
1215      }
1216      if (!infoBody.ContainKey(std::string(PlayerKeys::PLAYER_DRM_INFO_ADDR))) {
1217          MEDIA_LOGW("there's no drminfo-update drm_info_addr key");
1218          return;
1219      }
1220      if (!infoBody.ContainKey(std::string(PlayerKeys::PLAYER_DRM_INFO_COUNT))) {
1221          MEDIA_LOGW("there's no drminfo-update drm_info_count key");
1222          return;
1223      }
1224  
1225      uint8_t *drmInfoAddr = nullptr;
1226      size_t size  = 0;
1227      int32_t infoCount = 0;
1228      infoBody.GetBuffer(std::string(PlayerKeys::PLAYER_DRM_INFO_ADDR), &drmInfoAddr, size);
1229      CHECK_AND_RETURN_LOG(drmInfoAddr != nullptr && size > 0, "get drminfo buffer failed");
1230      infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_DRM_INFO_COUNT), infoCount);
1231      CHECK_AND_RETURN_LOG(infoCount > 0, "get drminfo count is illegal");
1232  
1233      std::multimap<std::string, std::vector<uint8_t>> drmInfoMap;
1234      int32_t ret = SetDrmInfoData(drmInfoAddr, infoCount, drmInfoMap);
1235      CHECK_AND_RETURN_LOG(ret == MSERR_OK, "SetDrmInfoData err");
1236      NapiCallback::ObjectArray *cb = new(std::nothrow) NapiCallback::ObjectArray();
1237      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new ObjectArray");
1238      cb->callback = refMap_.at(AVPlayerEvent::EVENT_DRM_INFO_UPDATE);
1239      cb->callbackName = AVPlayerEvent::EVENT_DRM_INFO_UPDATE;
1240      cb->infoMap = drmInfoMap;
1241      NapiCallback::CompleteCallback(env_, cb);
1242  }
1243  
OnSetDecryptConfigDoneCb(const int32_t extra,const Format & infoBody)1244  void AVPlayerCallback::OnSetDecryptConfigDoneCb(const int32_t extra, const Format &infoBody)
1245  {
1246      (void)extra;
1247      MEDIA_LOGI("AVPlayerCallback OnSetDecryptConfigDoneCb is called");
1248      if (refMap_.find(AVPlayerEvent::EVENT_SET_DECRYPT_CONFIG_DONE) == refMap_.end()) {
1249          MEDIA_LOGW("can not find SetDecryptConfig Done callback!");
1250          return;
1251      }
1252  
1253      NapiCallback::Base *cb = new(std::nothrow) NapiCallback::Base();
1254      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Base");
1255  
1256      cb->callback = refMap_.at(AVPlayerEvent::EVENT_SET_DECRYPT_CONFIG_DONE);
1257      cb->callbackName = AVPlayerEvent::EVENT_SET_DECRYPT_CONFIG_DONE;
1258      NapiCallback::CompleteCallback(env_, cb);
1259  }
1260  
OnSubtitleInfoCb(const int32_t extra,const Format & infoBody)1261  void AVPlayerCallback::OnSubtitleInfoCb(const int32_t extra, const Format &infoBody)
1262  {
1263      (void)infoBody;
1264      int32_t pts = -1;
1265      int32_t duration = -1;
1266      std::string text;
1267      infoBody.GetStringValue(PlayerKeys::SUBTITLE_TEXT, text);
1268      infoBody.GetIntValue(std::string(PlayerKeys::SUBTITLE_PTS), pts);
1269      infoBody.GetIntValue(std::string(PlayerKeys::SUBTITLE_DURATION), duration);
1270      MEDIA_LOGI("OnSubtitleInfoCb pts %{public}d, duration = %{public}d", pts, duration);
1271  
1272      CHECK_AND_RETURN_LOG(refMap_.find(AVPlayerEvent::EVENT_SUBTITLE_UPDATE) != refMap_.end(),
1273          "can not find Subtitle callback!");
1274  
1275      NapiCallback::SubtitleInfo *cb = new(std::nothrow) NapiCallback::SubtitleInfo();
1276      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Subtitle");
1277  
1278      cb->callback = refMap_.at(AVPlayerEvent::EVENT_SUBTITLE_UPDATE);
1279      cb->callbackName = AVPlayerEvent::EVENT_SUBTITLE_UPDATE;
1280      cb->valueMap.text = text;
1281      cb->valueMap.pts = pts;
1282      cb->valueMap.duration = duration;
1283  
1284      NapiCallback::CompleteCallback(env_, cb);
1285  }
1286  
OnEosCb(const int32_t extra,const Format & infoBody)1287  void AVPlayerCallback::OnEosCb(const int32_t extra, const Format &infoBody)
1288  {
1289      (void)infoBody;
1290      CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
1291      int32_t isLooping = extra;
1292      MEDIA_LOGI("0x%{public}06" PRIXPTR " OnEndOfStream is called, isloop: %{public}d", FAKE_POINTER(this), isLooping);
1293      if (refMap_.find(AVPlayerEvent::EVENT_END_OF_STREAM) == refMap_.end()) {
1294          MEDIA_LOGW("0x%{public}06" PRIXPTR " can not find EndOfStream callback!", FAKE_POINTER(this));
1295          return;
1296      }
1297  
1298      NapiCallback::Base *cb = new(std::nothrow) NapiCallback::Base();
1299      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Base");
1300  
1301      cb->callback = refMap_.at(AVPlayerEvent::EVENT_END_OF_STREAM);
1302      cb->callbackName = AVPlayerEvent::EVENT_END_OF_STREAM;
1303      NapiCallback::CompleteCallback(env_, cb);
1304  }
1305  
OnTrackChangedCb(const int32_t extra,const Format & infoBody)1306  void AVPlayerCallback::OnTrackChangedCb(const int32_t extra, const Format &infoBody)
1307  {
1308      (void)extra;
1309      int32_t index = -1;
1310      int32_t isSelect = -1;
1311      infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), index);
1312      infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_IS_SELECT), isSelect);
1313      MEDIA_LOGI("OnTrackChangedCb index %{public}d, isSelect = %{public}d", index, isSelect);
1314  
1315      CHECK_AND_RETURN_LOG(refMap_.find(AVPlayerEvent::EVENT_TRACKCHANGE) != refMap_.end(),
1316          "can not find trackChange callback!");
1317  
1318      NapiCallback::TrackChange *cb = new(std::nothrow) NapiCallback::TrackChange();
1319      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new TrackChange");
1320  
1321      cb->callback = refMap_.at(AVPlayerEvent::EVENT_TRACKCHANGE);
1322      cb->callbackName = AVPlayerEvent::EVENT_TRACKCHANGE;
1323      cb->number = index;
1324      cb->isSelect = isSelect ? true : false;
1325      NapiCallback::CompleteCallback(env_, cb);
1326  }
1327  
OnTrackInfoUpdate(const int32_t extra,const Format & infoBody)1328  void AVPlayerCallback::OnTrackInfoUpdate(const int32_t extra, const Format &infoBody)
1329  {
1330      (void)extra;
1331      std::vector<Format> trackInfo;
1332      (void)infoBody.GetFormatVector(std::string(PlayerKeys::PLAYER_TRACK_INFO), trackInfo);
1333      MEDIA_LOGI("OnTrackInfoUpdate callback");
1334  
1335      CHECK_AND_RETURN_LOG(refMap_.find(AVPlayerEvent::EVENT_TRACK_INFO_UPDATE) != refMap_.end(),
1336          "can not find trackInfoUpdate callback!");
1337  
1338      NapiCallback::TrackInfoUpdate *cb = new(std::nothrow) NapiCallback::TrackInfoUpdate();
1339      CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new TrackInfoUpdate");
1340  
1341      cb->callback = refMap_.at(AVPlayerEvent::EVENT_TRACK_INFO_UPDATE);
1342      cb->callbackName = AVPlayerEvent::EVENT_TRACK_INFO_UPDATE;
1343      cb->trackInfo = trackInfo;
1344      NapiCallback::CompleteCallback(env_, cb);
1345  }
1346  
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)1347  void AVPlayerCallback::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
1348  {
1349      std::lock_guard<std::mutex> lock(mutex_);
1350      refMap_[name] = ref;
1351  }
1352  
ClearCallbackReference()1353  void AVPlayerCallback::ClearCallbackReference()
1354  {
1355      std::lock_guard<std::mutex> lock(mutex_);
1356      refMap_.clear();
1357  }
1358  
ClearCallbackReference(const std::string & name)1359  void AVPlayerCallback::ClearCallbackReference(const std::string &name)
1360  {
1361      std::lock_guard<std::mutex> lock(mutex_);
1362      refMap_.erase(name);
1363  }
1364  
Start()1365  void AVPlayerCallback::Start()
1366  {
1367      isloaded_ = true;
1368  }
1369  
Pause()1370  void AVPlayerCallback::Pause()
1371  {
1372      isloaded_ = false;
1373  }
1374  
Release()1375  void AVPlayerCallback::Release()
1376  {
1377      std::lock_guard<std::mutex> lock(mutex_);
1378  
1379      Format infoBody;
1380      AVPlayerCallback::OnStateChangeCb(PlayerStates::PLAYER_RELEASED, infoBody);
1381      listener_ = nullptr;
1382  }
1383  } // namespace Media
1384  } // namespace OHOS
1385