• 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/declarative_frontend/jsview/js_utils.h"
20 #include "bridge/declarative_frontend/jsview/js_video_controller.h"
21 #include "bridge/declarative_frontend/jsview/models/video_model_impl.h"
22 #include "core/components_ng/pattern/video/video_model_ng.h"
23 #ifdef SUPPORT_JSSTACK
24 #include "xpower_event_jsvm.h"
25 #endif
26 
27 namespace OHOS::Ace {
28 
29 std::unique_ptr<VideoModel> VideoModel::instance_ = nullptr;
30 std::mutex VideoModel::mutex_;
31 
GetInstance()32 VideoModel* VideoModel::GetInstance()
33 {
34     if (!instance_) {
35         std::lock_guard<std::mutex> lock(mutex_);
36         if (!instance_) {
37 #ifdef NG_BUILD
38             instance_.reset(new NG::VideoModelNG());
39 #else
40             if (Container::IsCurrentUseNewPipeline()) {
41                 instance_.reset(new NG::VideoModelNG());
42             } else {
43                 instance_.reset(new Framework::VideoModelImpl());
44             }
45 #endif
46         }
47     }
48     return instance_.get();
49 }
50 
51 } // namespace OHOS::Ace
52 
53 namespace OHOS::Ace::Framework {
54 
Create(const JSCallbackInfo & info)55 void JSVideo::Create(const JSCallbackInfo& info)
56 {
57     if (!info[0]->IsObject()) {
58         return;
59     }
60     JSRef<JSObject> videoObj = JSRef<JSObject>::Cast(info[0]);
61     JSRef<JSVal> srcValue = videoObj->GetProperty("src");
62     JSRef<JSVal> previewUriValue = videoObj->GetProperty("previewUri");
63     JSRef<JSVal> currentProgressRateValue = videoObj->GetProperty("currentProgressRate");
64 
65     auto controllerObj = videoObj->GetProperty("controller");
66     RefPtr<VideoControllerV2> videoController = nullptr;
67     if (controllerObj->IsObject()) {
68         auto* jsVideoController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSVideoController>();
69         if (jsVideoController) {
70             videoController = jsVideoController->GetController();
71         }
72     }
73     VideoModel::GetInstance()->Create(videoController);
74 
75     // Parse the src, if it is invalid, use the empty string.
76     std::string videoSrc;
77     if (!ParseJsMedia(srcValue, videoSrc)) {
78         LOGW("Video parse src failed.");
79     }
80     VideoModel::GetInstance()->SetSrc(videoSrc);
81 
82     // Parse the rate, if it is invalid, set it as 1.0.
83     double currentProgressRate = 1.0;
84     if (!ParseJsDouble(currentProgressRateValue, currentProgressRate)) {
85         LOGW("Video parse currentProgressRate failed.");
86     }
87     VideoModel::GetInstance()->SetProgressRate(currentProgressRate);
88 
89     std::string previewUri;
90     if (previewUriValue->IsUndefined() || previewUriValue->IsNull()) {
91         // When it is undefined, just set the empty image.
92         LOGW("Video parse previewUri failed, it is null.");
93         VideoModel::GetInstance()->SetPosterSourceInfo(previewUri);
94         return;
95     }
96     auto noPixMap = ParseJsMedia(previewUriValue, previewUri);
97     if (noPixMap) {
98         // Src is a string or resource
99         VideoModel::GetInstance()->SetPosterSourceInfo(previewUri);
100     } else {
101         // Src is a pixelmap.
102 #if defined(PIXEL_MAP_SUPPORTED)
103         RefPtr<PixelMap> pixMap = CreatePixelMapFromNapiValue(previewUriValue);
104         VideoModel::GetInstance()->SetPosterSourceByPixelMap(pixMap);
105 #endif
106     }
107 }
108 
JsMuted(const JSCallbackInfo & info)109 void JSVideo::JsMuted(const JSCallbackInfo& info)
110 {
111     bool muted = false;
112     if (info[0]->IsBoolean()) {
113         muted = info[0]->ToBoolean();
114 #ifdef SUPPORT_JSSTACK
115         HiviewDFX::ReportXPowerJsStackSysEvent(info.GetVm(), "VOLUME_CHANGE", "SRC=Video");
116 #endif
117     }
118     VideoModel::GetInstance()->SetMuted(muted);
119 }
120 
JsAutoPlay(const JSCallbackInfo & info)121 void JSVideo::JsAutoPlay(const JSCallbackInfo& info)
122 {
123     bool autoPlay = false;
124     if (info[0]->IsBoolean()) {
125         autoPlay = info[0]->ToBoolean();
126 #ifdef SUPPORT_JSSTACK
127         HiviewDFX::ReportXPowerJsStackSysEvent(info.GetVm(), "STREAM_CHANGE", "SRC=Video");
128 #endif
129     }
130     VideoModel::GetInstance()->SetAutoPlay(autoPlay);
131 }
132 
JsControls(const JSCallbackInfo & info)133 void JSVideo::JsControls(const JSCallbackInfo& info)
134 {
135     bool controls = true;
136     if (info[0]->IsBoolean()) {
137         controls = info[0]->ToBoolean();
138     }
139     VideoModel::GetInstance()->SetControls(controls);
140 }
141 
JsLoop(const JSCallbackInfo & info)142 void JSVideo::JsLoop(const JSCallbackInfo& info)
143 {
144     bool loop = false;
145     if (info[0]->IsBoolean()) {
146         loop = info[0]->ToBoolean();
147     }
148     VideoModel::GetInstance()->SetLoop(loop);
149 }
150 
JsObjectFit(const JSCallbackInfo & info)151 void JSVideo::JsObjectFit(const JSCallbackInfo& info)
152 {
153     ImageFit imageFit = ImageFit::COVER;
154     // The default value of Imagefit is FILL, but in the video the default value is COVER.
155     // So the default value need to be converted.
156     if (info[0]->IsUndefined()) {
157         VideoModel::GetInstance()->SetObjectFit(imageFit);
158         return;
159     }
160     if (info[0]->IsNumber()) {
161         imageFit = static_cast<ImageFit>(info[0]->ToNumber<int>());
162     }
163     VideoModel::GetInstance()->SetObjectFit(imageFit);
164 }
165 
JsOnStart(const JSCallbackInfo & info)166 void JSVideo::JsOnStart(const JSCallbackInfo& info)
167 {
168     if (!info[0]->IsFunction()) {
169         return;
170     }
171     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
172     auto onStart = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
173         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
174         ACE_SCORING_EVENT("Video.onStart");
175         std::vector<std::string> keys = { "start" };
176         func->Execute(keys, param);
177     };
178     VideoModel::GetInstance()->SetOnStart(std::move(onStart));
179 }
180 
JsOnPause(const JSCallbackInfo & info)181 void JSVideo::JsOnPause(const JSCallbackInfo& info)
182 {
183     if (!info[0]->IsFunction()) {
184         return;
185     }
186     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
187     auto onPause = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
188         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
189         ACE_SCORING_EVENT("Video.onPause");
190         std::vector<std::string> keys = { "pause" };
191         func->Execute(keys, param);
192     };
193     VideoModel::GetInstance()->SetOnPause(std::move(onPause));
194 }
195 
JsOnFinish(const JSCallbackInfo & info)196 void JSVideo::JsOnFinish(const JSCallbackInfo& info)
197 {
198     if (!info[0]->IsFunction()) {
199         return;
200     }
201     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
202     auto onFinish = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
203         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
204         ACE_SCORING_EVENT("Video.onFinish");
205         std::vector<std::string> keys = { "finish" };
206         func->Execute(keys, param);
207     };
208     VideoModel::GetInstance()->SetOnFinish(std::move(onFinish));
209 }
210 
JsOnFullscreenChange(const JSCallbackInfo & info)211 void JSVideo::JsOnFullscreenChange(const JSCallbackInfo& info)
212 {
213     if (!info[0]->IsFunction()) {
214         return;
215     }
216     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
217     auto OnFullScreenChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
218                                   const std::string& param) {
219         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
220         ACE_SCORING_EVENT("Video.OnFullScreenChange");
221         std::vector<std::string> keys = { "fullscreen" };
222         func->Execute(keys, param);
223     };
224     VideoModel::GetInstance()->SetOnFullScreenChange(std::move(OnFullScreenChange));
225 }
226 
JsOnPrepared(const JSCallbackInfo & info)227 void JSVideo::JsOnPrepared(const JSCallbackInfo& info)
228 {
229     if (!info[0]->IsFunction()) {
230         return;
231     }
232     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
233     auto onPrepared = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
234         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
235         ACE_SCORING_EVENT("Video.onPrepared");
236         std::vector<std::string> keys = { "duration" };
237         func->Execute(keys, param);
238     };
239     VideoModel::GetInstance()->SetOnPrepared(std::move(onPrepared));
240 }
241 
JsOnSeeking(const JSCallbackInfo & info)242 void JSVideo::JsOnSeeking(const JSCallbackInfo& info)
243 {
244     if (!info[0]->IsFunction()) {
245         return;
246     }
247     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
248     auto onSeeking = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
249         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
250         ACE_SCORING_EVENT("Video.onSeeking");
251         std::vector<std::string> keys = { "time" };
252         func->Execute(keys, param);
253     };
254     VideoModel::GetInstance()->SetOnSeeking(std::move(onSeeking));
255 }
256 
JsOnSeeked(const JSCallbackInfo & info)257 void JSVideo::JsOnSeeked(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     auto onSeeked = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
264         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
265         ACE_SCORING_EVENT("Video.onSeeked");
266         std::vector<std::string> keys = { "time" };
267         func->Execute(keys, param);
268     };
269     VideoModel::GetInstance()->SetOnSeeked(std::move(onSeeked));
270 }
271 
JsOnUpdate(const JSCallbackInfo & info)272 void JSVideo::JsOnUpdate(const JSCallbackInfo& info)
273 {
274     if (!info[0]->IsFunction()) {
275         return;
276     }
277     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
278     auto onUpdate = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
279         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
280         ACE_SCORING_EVENT("Video.onUpdate");
281         std::vector<std::string> keys = { "time" };
282         func->Execute(keys, param);
283     };
284     VideoModel::GetInstance()->SetOnUpdate(std::move(onUpdate));
285 }
286 
JsOnError(const JSCallbackInfo & info)287 void JSVideo::JsOnError(const JSCallbackInfo& info)
288 {
289     if (!info[0]->IsFunction()) {
290         return;
291     }
292     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
293     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
294         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
295         ACE_SCORING_EVENT("Video.onError");
296         std::vector<std::string> keys = { "error" };
297         func->Execute(keys, param);
298     };
299     VideoModel::GetInstance()->SetOnError(std::move(onError));
300 }
301 
GetEventMarker(const JSCallbackInfo & info,const std::vector<std::string> & keys)302 EventMarker JSVideo::GetEventMarker(const JSCallbackInfo& info, const std::vector<std::string>& keys)
303 {
304     if (!info[0]->IsFunction()) {
305         return EventMarker();
306     }
307 
308     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
309     auto eventMarker =
310         EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys](const std::string& param) {
311             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
312             func->Execute(keys, param);
313         });
314     return eventMarker;
315 }
316 
JSBind(BindingTarget globalObj)317 void JSVideo::JSBind(BindingTarget globalObj)
318 {
319     JSClass<JSVideo>::Declare("Video");
320     MethodOptions opt = MethodOptions::NONE;
321     JSClass<JSVideo>::StaticMethod("create", &JSVideo::Create, opt);
322     JSClass<JSVideo>::StaticMethod("muted", &JSVideo::JsMuted, opt);
323     JSClass<JSVideo>::StaticMethod("autoPlay", &JSVideo::JsAutoPlay, opt);
324     JSClass<JSVideo>::StaticMethod("controls", &JSVideo::JsControls, opt);
325     JSClass<JSVideo>::StaticMethod("loop", &JSVideo::JsLoop, opt);
326     JSClass<JSVideo>::StaticMethod("objectFit", &JSVideo::JsObjectFit, opt);
327 
328     JSClass<JSVideo>::StaticMethod("onStart", &JSVideo::JsOnStart);
329     JSClass<JSVideo>::StaticMethod("onPause", &JSVideo::JsOnPause);
330     JSClass<JSVideo>::StaticMethod("onFinish", &JSVideo::JsOnFinish);
331     JSClass<JSVideo>::StaticMethod("onFullscreenChange", &JSVideo::JsOnFullscreenChange);
332     JSClass<JSVideo>::StaticMethod("onPrepared", &JSVideo::JsOnPrepared);
333     JSClass<JSVideo>::StaticMethod("onSeeking", &JSVideo::JsOnSeeking);
334     JSClass<JSVideo>::StaticMethod("onSeeked", &JSVideo::JsOnSeeked);
335     JSClass<JSVideo>::StaticMethod("onUpdate", &JSVideo::JsOnUpdate);
336     JSClass<JSVideo>::StaticMethod("onError", &JSVideo::JsOnError);
337 
338     JSClass<JSVideo>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
339     JSClass<JSVideo>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
340     JSClass<JSVideo>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
341     JSClass<JSVideo>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
342     JSClass<JSVideo>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
343     JSClass<JSVideo>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
344     JSClass<JSVideo>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
345     JSClass<JSVideo>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
346     // override method
347     JSClass<JSVideo>::StaticMethod("opacity", &JSViewAbstract::JsOpacityPassThrough);
348     JSClass<JSVideo>::StaticMethod("transition", &JSViewAbstract::JsTransitionPassThrough);
349     JSClass<JSVideo>::InheritAndBind<JSViewAbstract>(globalObj);
350 }
351 
352 } // namespace OHOS::Ace::Framework
353