• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "frameworks/bridge/declarative_frontend/jsview/js_video.h"
17 
18 #include "base/log/ace_scoring_log.h"
19 #include "bridge/common/utils/engine_helper.h"
20 #include "bridge/declarative_frontend/jsview/js_utils.h"
21 #include "bridge/declarative_frontend/jsview/js_video_controller.h"
22 #include "bridge/declarative_frontend/jsview/models/video_model_impl.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 #include "core/components_ng/pattern/video/video_model_ng.h"
25 #ifdef SUPPORT_JSSTACK
26 #include "xpower_event_jsvm.h"
27 #endif
28 
29 namespace OHOS::Ace {
30 
31 std::unique_ptr<VideoModel> VideoModel::instance_ = nullptr;
32 std::mutex VideoModel::mutex_;
33 
GetInstance()34 VideoModel* VideoModel::GetInstance()
35 {
36     if (!instance_) {
37         std::lock_guard<std::mutex> lock(mutex_);
38         if (!instance_) {
39 #ifdef NG_BUILD
40             instance_.reset(new NG::VideoModelNG());
41 #else
42             if (Container::IsCurrentUseNewPipeline()) {
43                 instance_.reset(new NG::VideoModelNG());
44             } else {
45                 instance_.reset(new Framework::VideoModelImpl());
46             }
47 #endif
48         }
49     }
50     return instance_.get();
51 }
52 
53 } // namespace OHOS::Ace
54 
55 namespace OHOS::Ace::Framework {
56 
Create(const JSCallbackInfo & info)57 void JSVideo::Create(const JSCallbackInfo& info)
58 {
59     if (!info[0]->IsObject()) {
60         return;
61     }
62     JSRef<JSObject> videoObj = JSRef<JSObject>::Cast(info[0]);
63     JSRef<JSVal> srcValue = videoObj->GetProperty("src");
64     JSRef<JSVal> previewUriValue = videoObj->GetProperty("previewUri");
65     JSRef<JSVal> currentProgressRateValue = videoObj->GetProperty("currentProgressRate");
66 
67     auto controllerObj = videoObj->GetProperty("controller");
68     RefPtr<VideoControllerV2> videoController = nullptr;
69     if (controllerObj->IsObject()) {
70         auto* jsVideoController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSVideoController>();
71         if (jsVideoController) {
72             jsVideoController->SetInstanceId(Container::CurrentId());
73             videoController = jsVideoController->GetController();
74         }
75     }
76     VideoModel::GetInstance()->Create(videoController);
77 
78     // Parse the src, if it is invalid, use the empty string.
79     std::string videoSrc;
80     ParseJsMedia(srcValue, videoSrc);
81     VideoModel::GetInstance()->SetSrc(videoSrc);
82 
83     // Parse the rate, if it is invalid, set it as 1.0.
84     double currentProgressRate = 1.0;
85     ParseJsDouble(currentProgressRateValue, currentProgressRate);
86     VideoModel::GetInstance()->SetProgressRate(currentProgressRate);
87 
88     auto aiOptions = videoObj->GetProperty("imageAIOptions");
89     if (aiOptions->IsObject()) {
90         ParseImageAIOptions(aiOptions);
91     }
92 
93     std::string previewUri;
94     std::string bundleName;
95     std::string moduleName;
96     GetJsMediaBundleInfo(previewUriValue, bundleName, moduleName);
97     if (previewUriValue->IsUndefined() || previewUriValue->IsNull()) {
98         // When it is undefined, just set the empty image.
99         VideoModel::GetInstance()->SetPosterSourceInfo(previewUri, "", "");
100         return;
101     }
102     auto noPixMap = ParseJsMedia(previewUriValue, previewUri);
103     if (noPixMap) {
104         // Src is a string or resource
105         VideoModel::GetInstance()->SetPosterSourceInfo(previewUri, bundleName, moduleName);
106     } else {
107         // Src is a pixelmap.
108 #if defined(PIXEL_MAP_SUPPORTED)
109         RefPtr<PixelMap> pixMap = CreatePixelMapFromNapiValue(previewUriValue);
110         VideoModel::GetInstance()->SetPosterSourceByPixelMap(pixMap);
111 #endif
112     }
113 }
114 
ParseImageAIOptions(const JSRef<JSVal> & jsValue)115 void JSVideo::ParseImageAIOptions(const JSRef<JSVal>& jsValue)
116 {
117     auto engine = EngineHelper::GetCurrentEngine();
118     CHECK_NULL_VOID(engine);
119     NativeEngine* nativeEngine = engine->GetNativeEngine();
120     CHECK_NULL_VOID(nativeEngine);
121     panda::Local<JsiValue> value = jsValue.Get().GetLocalHandle();
122     JSValueWrapper valueWrapper = value;
123     ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
124     napi_value optionsValue = nativeEngine->ValueToNapiValue(valueWrapper);
125     VideoModel::GetInstance()->SetImageAIOptions(optionsValue);
126 }
127 
JsMuted(const JSCallbackInfo & info)128 void JSVideo::JsMuted(const JSCallbackInfo& info)
129 {
130     bool muted = false;
131     if (info[0]->IsBoolean()) {
132         muted = info[0]->ToBoolean();
133 #ifdef SUPPORT_JSSTACK
134         HiviewDFX::ReportXPowerJsStackSysEvent(info.GetVm(), "VOLUME_CHANGE", "SRC=Video");
135 #endif
136     }
137     VideoModel::GetInstance()->SetMuted(muted);
138 }
139 
JsAutoPlay(const JSCallbackInfo & info)140 void JSVideo::JsAutoPlay(const JSCallbackInfo& info)
141 {
142     bool autoPlay = false;
143     if (info[0]->IsBoolean()) {
144         autoPlay = info[0]->ToBoolean();
145 #ifdef SUPPORT_JSSTACK
146         HiviewDFX::ReportXPowerJsStackSysEvent(info.GetVm(), "STREAM_CHANGE", "SRC=Video");
147 #endif
148     }
149     VideoModel::GetInstance()->SetAutoPlay(autoPlay);
150 }
151 
JsControls(const JSCallbackInfo & info)152 void JSVideo::JsControls(const JSCallbackInfo& info)
153 {
154     bool controls = true;
155     if (info[0]->IsBoolean()) {
156         controls = info[0]->ToBoolean();
157     }
158     VideoModel::GetInstance()->SetControls(controls);
159 }
160 
JsLoop(const JSCallbackInfo & info)161 void JSVideo::JsLoop(const JSCallbackInfo& info)
162 {
163     bool loop = false;
164     if (info[0]->IsBoolean()) {
165         loop = info[0]->ToBoolean();
166     }
167     VideoModel::GetInstance()->SetLoop(loop);
168 }
169 
JsObjectFit(const JSCallbackInfo & info)170 void JSVideo::JsObjectFit(const JSCallbackInfo& info)
171 {
172     ImageFit imageFit = ImageFit::COVER;
173     // The default value of Imagefit is FILL, but in the video the default value is COVER.
174     // So the default value need to be converted.
175     if (info[0]->IsUndefined()) {
176         VideoModel::GetInstance()->SetObjectFit(imageFit);
177         return;
178     }
179     if (info[0]->IsNumber()) {
180         imageFit = static_cast<ImageFit>(info[0]->ToNumber<int>());
181     }
182     VideoModel::GetInstance()->SetObjectFit(imageFit);
183 }
184 
JsOnStart(const JSCallbackInfo & info)185 void JSVideo::JsOnStart(const JSCallbackInfo& info)
186 {
187     if (!info[0]->IsFunction()) {
188         return;
189     }
190     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
191     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
192     auto onStart = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
193                        const std::string& param) {
194         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
195         ACE_SCORING_EVENT("Video.onStart");
196         PipelineContext::SetCallBackNode(node);
197         std::vector<std::string> keys = { "start" };
198         func->Execute(keys, param);
199     };
200     VideoModel::GetInstance()->SetOnStart(std::move(onStart));
201 }
202 
JsOnPause(const JSCallbackInfo & info)203 void JSVideo::JsOnPause(const JSCallbackInfo& info)
204 {
205     if (!info[0]->IsFunction()) {
206         return;
207     }
208     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
209     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
210     auto onPause = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
211                        const std::string& param) {
212         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
213         ACE_SCORING_EVENT("Video.onPause");
214         PipelineContext::SetCallBackNode(node);
215         std::vector<std::string> keys = { "pause" };
216         func->Execute(keys, param);
217     };
218     VideoModel::GetInstance()->SetOnPause(std::move(onPause));
219 }
220 
JsOnFinish(const JSCallbackInfo & info)221 void JSVideo::JsOnFinish(const JSCallbackInfo& info)
222 {
223     if (!info[0]->IsFunction()) {
224         return;
225     }
226     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
227     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
228     auto onFinish = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
229                         const std::string& param) {
230         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
231         ACE_SCORING_EVENT("Video.onFinish");
232         PipelineContext::SetCallBackNode(node);
233         std::vector<std::string> keys = { "finish" };
234         func->Execute(keys, param);
235     };
236     VideoModel::GetInstance()->SetOnFinish(std::move(onFinish));
237 }
238 
JsOnStop(const JSCallbackInfo & info)239 void JSVideo::JsOnStop(const JSCallbackInfo& info)
240 {
241     if (!info[0]->IsFunction()) {
242         return;
243     }
244     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
245     auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
246     auto onStop = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
247                         const std::string& param) {
248         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
249         ACE_SCORING_EVENT("Video.onStop");
250         PipelineContext::SetCallBackNode(node);
251         std::vector<std::string> keys = { "stop" };
252         func->Execute(keys, param);
253     };
254     VideoModel::GetInstance()->SetOnStop(std::move(onStop));
255 }
256 
JsOnFullscreenChange(const JSCallbackInfo & info)257 void JSVideo::JsOnFullscreenChange(const JSCallbackInfo& info)
258 {
259     if (!info[0]->IsFunction()) {
260         return;
261     }
262     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
263     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
264     auto OnFullScreenChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
265                                   const std::string& param) {
266         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
267         ACE_SCORING_EVENT("Video.OnFullScreenChange");
268         PipelineContext::SetCallBackNode(node);
269         std::vector<std::string> keys = { "fullscreen" };
270         func->Execute(keys, param);
271     };
272     VideoModel::GetInstance()->SetOnFullScreenChange(std::move(OnFullScreenChange));
273 }
274 
JsOnPrepared(const JSCallbackInfo & info)275 void JSVideo::JsOnPrepared(const JSCallbackInfo& info)
276 {
277     if (!info[0]->IsFunction()) {
278         return;
279     }
280     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
281     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
282     auto onPrepared = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
283                           const std::string& param) {
284         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
285         ACE_SCORING_EVENT("Video.onPrepared");
286         PipelineContext::SetCallBackNode(node);
287         std::vector<std::string> keys = { "duration" };
288         func->Execute(keys, param);
289     };
290     VideoModel::GetInstance()->SetOnPrepared(std::move(onPrepared));
291 }
292 
JsOnSeeking(const JSCallbackInfo & info)293 void JSVideo::JsOnSeeking(const JSCallbackInfo& info)
294 {
295     if (!info[0]->IsFunction()) {
296         return;
297     }
298     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
299     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
300     auto onSeeking = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
301                          const std::string& param) {
302         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
303         ACE_SCORING_EVENT("Video.onSeeking");
304         PipelineContext::SetCallBackNode(node);
305         std::vector<std::string> keys = { "time" };
306         func->Execute(keys, param);
307     };
308     VideoModel::GetInstance()->SetOnSeeking(std::move(onSeeking));
309 }
310 
JsOnSeeked(const JSCallbackInfo & info)311 void JSVideo::JsOnSeeked(const JSCallbackInfo& info)
312 {
313     if (!info[0]->IsFunction()) {
314         return;
315     }
316     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
317     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
318     auto onSeeked = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
319                         const std::string& param) {
320         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
321         ACE_SCORING_EVENT("Video.onSeeked");
322         PipelineContext::SetCallBackNode(node);
323         std::vector<std::string> keys = { "time" };
324         func->Execute(keys, param);
325     };
326     VideoModel::GetInstance()->SetOnSeeked(std::move(onSeeked));
327 }
328 
JsOnUpdate(const JSCallbackInfo & info)329 void JSVideo::JsOnUpdate(const JSCallbackInfo& info)
330 {
331     if (!info[0]->IsFunction()) {
332         return;
333     }
334     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
335     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
336     auto onUpdate = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
337                         const std::string& param) {
338         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
339         ACE_SCORING_EVENT("Video.onUpdate");
340         PipelineContext::SetCallBackNode(node);
341         std::vector<std::string> keys = { "time" };
342         func->Execute(keys, param);
343     };
344     VideoModel::GetInstance()->SetOnUpdate(std::move(onUpdate));
345 }
346 
JsOnError(const JSCallbackInfo & info)347 void JSVideo::JsOnError(const JSCallbackInfo& info)
348 {
349     if (!info[0]->IsFunction()) {
350         return;
351     }
352     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
353     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
354     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
355                        const std::string& param) {
356         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
357         ACE_SCORING_EVENT("Video.onError");
358         PipelineContext::SetCallBackNode(node);
359         std::vector<std::string> keys = { "error" };
360         func->Execute(keys, param);
361     };
362     VideoModel::GetInstance()->SetOnError(std::move(onError));
363 }
364 
GetEventMarker(const JSCallbackInfo & info,const std::vector<std::string> & keys)365 EventMarker JSVideo::GetEventMarker(const JSCallbackInfo& info, const std::vector<std::string>& keys)
366 {
367     if (!info[0]->IsFunction()) {
368         return EventMarker();
369     }
370 
371     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
372     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
373     auto eventMarker = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys,
374                                        node = targetNode](const std::string& param) {
375         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
376         PipelineContext::SetCallBackNode(node);
377         func->Execute(keys, param);
378     });
379     return eventMarker;
380 }
381 
EnableAnalyzer(bool enable)382 void JSVideo::EnableAnalyzer(bool enable)
383 {
384     VideoModel::GetInstance()->EnableAnalyzer(enable);
385 }
386 
AnalyzerConfig(const JSCallbackInfo & info)387 void JSVideo::AnalyzerConfig(const JSCallbackInfo& info)
388 {
389     auto configParams = info[0];
390     if (configParams->IsNull() || !configParams->IsObject()) {
391         return;
392     }
393     auto engine = EngineHelper::GetCurrentEngine();
394     CHECK_NULL_VOID(engine);
395     NativeEngine* nativeEngine = engine->GetNativeEngine();
396     panda::Local<JsiValue> value = configParams.Get().GetLocalHandle();
397     JSValueWrapper valueWrapper = value;
398     ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
399     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
400     VideoModel::GetInstance()->SetImageAnalyzerConfig(nativeValue);
401 }
402 
JSBind(BindingTarget globalObj)403 void JSVideo::JSBind(BindingTarget globalObj)
404 {
405     JSClass<JSVideo>::Declare("Video");
406     MethodOptions opt = MethodOptions::NONE;
407     JSClass<JSVideo>::StaticMethod("create", &JSVideo::Create, opt);
408     JSClass<JSVideo>::StaticMethod("muted", &JSVideo::JsMuted, opt);
409     JSClass<JSVideo>::StaticMethod("autoPlay", &JSVideo::JsAutoPlay, opt);
410     JSClass<JSVideo>::StaticMethod("controls", &JSVideo::JsControls, opt);
411     JSClass<JSVideo>::StaticMethod("loop", &JSVideo::JsLoop, opt);
412     JSClass<JSVideo>::StaticMethod("objectFit", &JSVideo::JsObjectFit, opt);
413 
414     JSClass<JSVideo>::StaticMethod("onStart", &JSVideo::JsOnStart);
415     JSClass<JSVideo>::StaticMethod("onPause", &JSVideo::JsOnPause);
416     JSClass<JSVideo>::StaticMethod("onFinish", &JSVideo::JsOnFinish);
417     JSClass<JSVideo>::StaticMethod("onFullscreenChange", &JSVideo::JsOnFullscreenChange);
418     JSClass<JSVideo>::StaticMethod("onPrepared", &JSVideo::JsOnPrepared);
419     JSClass<JSVideo>::StaticMethod("onSeeking", &JSVideo::JsOnSeeking);
420     JSClass<JSVideo>::StaticMethod("onSeeked", &JSVideo::JsOnSeeked);
421     JSClass<JSVideo>::StaticMethod("onUpdate", &JSVideo::JsOnUpdate);
422     JSClass<JSVideo>::StaticMethod("onError", &JSVideo::JsOnError);
423     JSClass<JSVideo>::StaticMethod("onStop", &JSVideo::JsOnStop);
424     JSClass<JSVideo>::StaticMethod("enableAnalyzer", &JSVideo::EnableAnalyzer);
425     JSClass<JSVideo>::StaticMethod("analyzerConfig", &JSVideo::AnalyzerConfig);
426 
427     JSClass<JSVideo>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
428     JSClass<JSVideo>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
429     JSClass<JSVideo>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
430     JSClass<JSVideo>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
431     JSClass<JSVideo>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
432     JSClass<JSVideo>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
433     JSClass<JSVideo>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
434     JSClass<JSVideo>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
435     JSClass<JSVideo>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
436     JSClass<JSVideo>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
437     // override method
438     JSClass<JSVideo>::StaticMethod("opacity", &JSViewAbstract::JsOpacityPassThrough);
439     JSClass<JSVideo>::StaticMethod("transition", &JSViewAbstract::JsTransitionPassThrough);
440     JSClass<JSVideo>::InheritAndBind<JSViewAbstract>(globalObj);
441 }
442 
443 } // namespace OHOS::Ace::Framework
444