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 "core/components_ng/pattern/video/video_pattern.h"
17
18 #include "video_node.h"
19
20 #include "base/geometry/dimension.h"
21 #include "base/geometry/ng/size_t.h"
22 #include "base/i18n/localization.h"
23 #include "base/json/json_util.h"
24 #include "base/thread/task_executor.h"
25 #include "base/utils/string_utils.h"
26 #include "base/utils/system_properties.h"
27 #include "base/utils/utils.h"
28 #include "core/common/ace_engine.h"
29 #include "core/common/ace_view.h"
30 #include "core/common/container.h"
31 #include "core/common/udmf/udmf_client.h"
32 #include "core/components/common/layout/constants.h"
33 #include "core/components/common/properties/color.h"
34 #include "core/components/declaration/button/button_declaration.h"
35 #include "core/components/video/video_theme.h"
36 #include "core/components/video/video_utils.h"
37 #include "core/components_ng/pattern/button/button_event_hub.h"
38 #include "core/components_ng/pattern/button/button_layout_property.h"
39 #include "core/components_ng/pattern/button/button_pattern.h"
40 #include "core/components_ng/pattern/image/image_layout_property.h"
41 #include "core/components_ng/pattern/image/image_pattern.h"
42 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
43 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
44 #include "core/components_ng/pattern/slider/slider_event_hub.h"
45 #include "core/components_ng/pattern/slider/slider_layout_property.h"
46 #include "core/components_ng/pattern/slider/slider_paint_property.h"
47 #include "core/components_ng/pattern/slider/slider_pattern.h"
48 #include "core/components_ng/pattern/text/text_layout_property.h"
49 #include "core/components_ng/pattern/text/text_pattern.h"
50 #include "core/components_ng/pattern/video/video_event_hub.h"
51 #include "core/components_ng/pattern/video/video_full_screen_node.h"
52 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
53 #include "core/components_ng/pattern/video/video_layout_property.h"
54 #include "core/components_ng/pattern/video/video_node.h"
55 #include "core/components_ng/property/property.h"
56 #include "core/components_v2/inspector/inspector_constants.h"
57 #include "core/pipeline_ng/pipeline_context.h"
58 namespace OHOS::Ace::NG {
59 namespace {
60 constexpr uint32_t SECONDS_PER_HOUR = 3600;
61 constexpr uint32_t SECONDS_PER_MINUTE = 60;
62 const std::string FORMAT_HH_MM_SS = "%02d:%02d:%02d";
63 const std::string FORMAT_MM_SS = "%02d:%02d";
64 constexpr int32_t MILLISECONDS_TO_SECONDS = 1000;
65 constexpr uint32_t CURRENT_POS = 1;
66 constexpr uint32_t SLIDER_POS = 2;
67 constexpr uint32_t DURATION_POS = 3;
68 constexpr uint32_t FULL_SCREEN_POS = 4;
69 constexpr int32_t AVERAGE_VALUE = 2;
70 const Dimension LIFT_HEIGHT = 28.0_vp;
71
72 // Default error, empty string.
73 const std::string ERROR = "";
74
75 enum SliderChangeMode {
76 BEGIN = 0,
77 MOVING,
78 END,
79 };
80
IntTimeToText(uint32_t time)81 std::string IntTimeToText(uint32_t time)
82 {
83 auto minutes = (time % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
84 auto seconds = time % SECONDS_PER_MINUTE;
85 if (time >= SECONDS_PER_HOUR) {
86 auto hours = time / SECONDS_PER_HOUR;
87 return StringUtils::FormatString(FORMAT_HH_MM_SS.c_str(), hours, minutes, seconds);
88 }
89 return StringUtils::FormatString(FORMAT_MM_SS.c_str(), minutes, seconds);
90 }
91
CalculateFitContain(const SizeF & videoSize,const SizeF & layoutSize)92 SizeF CalculateFitContain(const SizeF& videoSize, const SizeF& layoutSize)
93 {
94 double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
95 double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
96
97 if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
98 return layoutSize;
99 }
100 if (sourceRatio < layoutRatio) {
101 return { static_cast<float>(sourceRatio) * layoutSize.Height(), layoutSize.Height() };
102 }
103 return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
104 }
105
CalculateFitFill(const SizeF & layoutSize)106 SizeF CalculateFitFill(const SizeF& layoutSize)
107 {
108 return layoutSize;
109 }
110
CalculateFitCover(const SizeF & videoSize,const SizeF & layoutSize)111 SizeF CalculateFitCover(const SizeF& videoSize, const SizeF& layoutSize)
112 {
113 double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
114 double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
115
116 if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
117 return layoutSize;
118 }
119 if (sourceRatio < layoutRatio) {
120 return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
121 }
122 return { static_cast<float>(layoutSize.Height() * sourceRatio), layoutSize.Height() };
123 }
124
CalculateFitNone(const SizeF & videoSize)125 SizeF CalculateFitNone(const SizeF& videoSize)
126 {
127 return videoSize;
128 }
129
CalculateFitScaleDown(const SizeF & videoSize,const SizeF & layoutSize)130 SizeF CalculateFitScaleDown(const SizeF& videoSize, const SizeF& layoutSize)
131 {
132 if (layoutSize.Width() > videoSize.Width()) {
133 return CalculateFitNone(videoSize);
134 }
135 return CalculateFitContain(videoSize, layoutSize);
136 }
137
MeasureVideoContentLayout(const SizeF & layoutSize,const RefPtr<VideoLayoutProperty> & layoutProperty)138 SizeF MeasureVideoContentLayout(const SizeF& layoutSize, const RefPtr<VideoLayoutProperty>& layoutProperty)
139 {
140 if (!layoutProperty || !layoutProperty->HasVideoSize()) {
141 return layoutSize;
142 }
143
144 auto videoSize = layoutProperty->GetVideoSizeValue(SizeF(0, 0));
145 auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
146 SizeF contentSize = { 0.0, 0.0 };
147 switch (imageFit) {
148 case ImageFit::CONTAIN:
149 contentSize = CalculateFitContain(videoSize, layoutSize);
150 break;
151 case ImageFit::FILL:
152 contentSize = CalculateFitFill(layoutSize);
153 break;
154 case ImageFit::COVER:
155 contentSize = CalculateFitCover(videoSize, layoutSize);
156 break;
157 case ImageFit::NONE:
158 contentSize = CalculateFitNone(videoSize);
159 break;
160 case ImageFit::SCALE_DOWN:
161 contentSize = CalculateFitScaleDown(videoSize, layoutSize);
162 break;
163 default:
164 contentSize = CalculateFitContain(videoSize, layoutSize);
165 }
166
167 // Just return contentSize as the video frame area.
168 return contentSize;
169 }
170 } // namespace
171
VideoPattern(const RefPtr<VideoControllerV2> & videoController)172 VideoPattern::VideoPattern(const RefPtr<VideoControllerV2>& videoController)
173 : instanceId_(Container::CurrentId()), videoControllerV2_(videoController)
174 {}
175
ResetStatus()176 void VideoPattern::ResetStatus()
177 {
178 isInitialState_ = true;
179 isPlaying_ = false;
180 #ifndef OHOS_PLATFORM
181 isStop_ = false;
182 #endif
183 }
184
ResetMediaPlayer()185 void VideoPattern::ResetMediaPlayer()
186 {
187 CHECK_NULL_VOID(mediaPlayer_);
188 mediaPlayer_->ResetMediaPlayer();
189 if (!SetSourceForMediaPlayer()) {
190 TAG_LOGW(AceLogTag::ACE_VIDEO, "Video set source for mediaPlayer failed.");
191
192 // It need post on ui thread.
193 FireError();
194 return;
195 }
196
197 RegisterMediaPlayerEvent();
198 PrepareSurface();
199 if (mediaPlayer_ && mediaPlayer_->PrepareAsync() != 0) {
200 TAG_LOGE(AceLogTag::ACE_VIDEO, "Player prepare failed");
201 }
202 }
203
UpdateMediaPlayerOnBg()204 void VideoPattern::UpdateMediaPlayerOnBg()
205 {
206 PrepareMediaPlayer();
207 UpdateSpeed();
208 UpdateLooping();
209 UpdateMuted();
210 if (isInitialState_ && autoPlay_) {
211 // When video is autoPlay, start playing the video when it is initial state.
212 Start();
213 }
214 }
215
PrepareMediaPlayer()216 void VideoPattern::PrepareMediaPlayer()
217 {
218 auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
219 CHECK_NULL_VOID(videoLayoutProperty);
220 // src has not set/changed
221 if (!videoLayoutProperty->HasVideoSource() || videoLayoutProperty->GetVideoSource().value() == src_) {
222 TAG_LOGI(AceLogTag::ACE_VIDEO, "Video source is null or the source has not changed.");
223 return;
224 }
225 src_ = videoLayoutProperty->GetVideoSource().value();
226 if (mediaPlayer_ && !mediaPlayer_->IsMediaPlayerValid()) {
227 mediaPlayer_->CreateMediaPlayer();
228 }
229
230 if (mediaPlayer_ && !mediaPlayer_->IsMediaPlayerValid()) {
231 // It need post on ui thread.
232 FireError();
233 return;
234 }
235
236 ResetStatus();
237 ContainerScope scope(instanceId_);
238 auto context = PipelineContext::GetCurrentContext();
239 CHECK_NULL_VOID(context);
240 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
241 platformTask.PostTask([weak = WeakClaim(this)] {
242 auto video = weak.Upgrade();
243 CHECK_NULL_VOID(video);
244 auto targetPattern = video->GetTargetVideoPattern();
245 CHECK_NULL_VOID(targetPattern);
246 targetPattern->ResetMediaPlayer();
247 });
248 }
249
SetSourceForMediaPlayer()250 bool VideoPattern::SetSourceForMediaPlayer()
251 {
252 TAG_LOGI(AceLogTag::ACE_VIDEO, "Video Set src for media, it is : %{public}s", src_.c_str());
253 CHECK_NULL_RETURN(mediaPlayer_, false);
254 return mediaPlayer_->SetSource(src_);
255 }
256
RegisterMediaPlayerEvent()257 void VideoPattern::RegisterMediaPlayerEvent()
258 {
259 if (src_.empty() || !mediaPlayer_) {
260 TAG_LOGW(AceLogTag::ACE_VIDEO, "Video src is empty or mediaPlayer is null, register mediaPlayerEvent fail");
261 return;
262 }
263 ContainerScope scope(instanceId_);
264 auto context = PipelineContext::GetCurrentContext();
265 CHECK_NULL_VOID(context);
266
267 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
268 auto videoPattern = WeakClaim(this);
269
270 auto&& positionUpdatedEvent = [videoPattern, uiTaskExecutor](uint32_t currentPos) {
271 uiTaskExecutor.PostSyncTask([&videoPattern, currentPos] {
272 auto video = videoPattern.Upgrade();
273 CHECK_NULL_VOID(video);
274 ContainerScope scope(video->instanceId_);
275 video->OnCurrentTimeChange(currentPos);
276 });
277 };
278
279 auto&& stateChangedEvent = [videoPattern, uiTaskExecutor](PlaybackStatus status) {
280 uiTaskExecutor.PostSyncTask([&videoPattern, status] {
281 auto video = videoPattern.Upgrade();
282 CHECK_NULL_VOID(video);
283 ContainerScope scope(video->instanceId_);
284 video->OnPlayerStatus(status);
285 });
286 };
287
288 auto&& errorEvent = [videoPattern, uiTaskExecutor]() {
289 uiTaskExecutor.PostTask([&videoPattern] {
290 auto video = videoPattern.Upgrade();
291 CHECK_NULL_VOID(video);
292 ContainerScope scope(video->instanceId_);
293 video->OnError("");
294 });
295 };
296
297 auto&& resolutionChangeEvent = [videoPattern, uiTaskExecutor]() {
298 uiTaskExecutor.PostSyncTask([&videoPattern] {
299 auto video = videoPattern.Upgrade();
300 CHECK_NULL_VOID(video);
301 ContainerScope scope(video->instanceId_);
302 video->OnResolutionChange();
303 });
304 };
305
306 auto&& startRenderFrameEvent = [videoPattern, uiTaskExecutor]() {
307 uiTaskExecutor.PostSyncTask([&videoPattern] {
308 auto video = videoPattern.Upgrade();
309 CHECK_NULL_VOID(video);
310 ContainerScope scope(video->instanceId_);
311 video->OnStartRenderFrameCb();
312 });
313 };
314
315 mediaPlayer_->RegisterMediaPlayerEvent(
316 positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
317
318 #ifdef VIDEO_TEXTURE_SUPPORTED
319 auto&& textureRefreshEvent = [videoPattern, uiTaskExecutor](int32_t instanceId, int64_t textureId) {
320 uiTaskExecutor.PostSyncTask([&videoPattern, instanceId, textureId] {
321 auto video = videoPattern.Upgrade();
322 CHECK_NULL_VOID(video);
323 void* nativeWindow = video->GetNativeWindow(instanceId, textureId);
324 if (!nativeWindow) {
325 LOGE("the native window is nullptr.");
326 return;
327 }
328 video->OnTextureRefresh(nativeWindow);
329 });
330 };
331 mediaPlayer_->RegisterTextureEvent(textureRefreshEvent);
332 #endif
333 }
334
335 #ifdef VIDEO_TEXTURE_SUPPORTED
GetNativeWindow(int32_t instanceId,int64_t textureId)336 void* VideoPattern::GetNativeWindow(int32_t instanceId, int64_t textureId)
337 {
338 auto container = AceEngine::Get().GetContainer(instanceId);
339 CHECK_NULL_RETURN(container, nullptr);
340 auto nativeView = static_cast<AceView*>(container->GetView());
341 CHECK_NULL_RETURN(nativeView, nullptr);
342 return const_cast<void*>(nativeView->GetNativeWindowById(textureId));
343 }
344
OnTextureRefresh(void * surface)345 void VideoPattern::OnTextureRefresh(void* surface)
346 {
347 CHECK_NULL_VOID(surface);
348 auto renderContextForMediaPlayer = renderContextForMediaPlayerWeakPtr_.Upgrade();
349 CHECK_NULL_VOID(renderContextForMediaPlayer);
350 renderContextForMediaPlayer->MarkNewFrameAvailable(surface);
351 }
352 #endif
353
PrintPlayerStatus(PlaybackStatus status)354 void VideoPattern::PrintPlayerStatus(PlaybackStatus status)
355 {
356 switch (status) {
357 case PlaybackStatus::ERROR:
358 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is ERROR.");
359 break;
360 case PlaybackStatus::IDLE:
361 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is IDLE.");
362 break;
363 case PlaybackStatus::PREPARED:
364 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PREPARED.");
365 break;
366 case PlaybackStatus::STARTED:
367 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is STARTED.");
368 break;
369 case PlaybackStatus::PAUSED:
370 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PAUSED.");
371 break;
372 case PlaybackStatus::STOPPED:
373 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is STOPPED.");
374 break;
375 case PlaybackStatus::PLAYBACK_COMPLETE:
376 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PLAYBACK_COMPLETE.");
377 break;
378 case PlaybackStatus::NONE:
379 TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is NONE.");
380 break;
381 default:
382 TAG_LOGW(AceLogTag::ACE_VIDEO, "Invalid player status.");
383 break;
384 }
385 }
386
OnCurrentTimeChange(uint32_t currentPos)387 void VideoPattern::OnCurrentTimeChange(uint32_t currentPos)
388 {
389 isInitialState_ = isInitialState_ ? currentPos == 0 : false;
390 if (currentPos == currentPos_ || isStop_) {
391 return;
392 }
393
394 if (duration_ == 0) {
395 int32_t duration = 0;
396 if (mediaPlayer_ && mediaPlayer_->GetDuration(duration) == 0) {
397 duration_ = duration / MILLISECONDS_TO_SECONDS;
398 OnUpdateTime(duration_, DURATION_POS);
399 }
400 }
401
402 OnUpdateTime(currentPos, CURRENT_POS);
403 currentPos_ = currentPos;
404 auto eventHub = GetEventHub<VideoEventHub>();
405 CHECK_NULL_VOID(eventHub);
406 auto json = JsonUtil::Create(true);
407 json->Put("time", static_cast<double>(currentPos));
408 auto param = json->ToString();
409 eventHub->FireUpdateEvent(param);
410 }
411
OnPlayerStatus(PlaybackStatus status)412 void VideoPattern::OnPlayerStatus(PlaybackStatus status)
413 {
414 PrintPlayerStatus(status);
415 bool isPlaying = (status == PlaybackStatus::STARTED);
416 if (isPlaying_ != isPlaying) {
417 isPlaying_ = isPlaying;
418 ChangePlayButtonTag();
419 }
420
421 if (isInitialState_) {
422 isInitialState_ = !isPlaying;
423 }
424
425 if (isPlaying) {
426 auto json = JsonUtil::Create(true);
427 json->Put("start", "");
428 auto param = json->ToString();
429 auto eventHub = GetEventHub<VideoEventHub>();
430 CHECK_NULL_VOID(eventHub);
431 eventHub->FireStartEvent(param);
432 }
433
434 if (status == PlaybackStatus::PAUSED) {
435 auto json = JsonUtil::Create(true);
436 json->Put("pause", "");
437 auto param = json->ToString();
438 auto eventHub = GetEventHub<VideoEventHub>();
439 CHECK_NULL_VOID(eventHub);
440 eventHub->FirePauseEvent(param);
441 }
442
443 if (status == PlaybackStatus::PREPARED) {
444 ContainerScope scope(instanceId_);
445 auto context = PipelineContext::GetCurrentContext();
446 CHECK_NULL_VOID(context);
447 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
448 return;
449 }
450 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
451 Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
452 int32_t milliSecondDuration = 0;
453 mediaPlayer_->GetDuration(milliSecondDuration);
454 OnPrepared(videoSize.Width(), videoSize.Height(), milliSecondDuration / MILLISECONDS_TO_SECONDS, 0, true);
455 return;
456 }
457
458 if (status == PlaybackStatus::PLAYBACK_COMPLETE) {
459 OnCompletion();
460 }
461 }
462
OnError(const std::string & errorId)463 void VideoPattern::OnError(const std::string& errorId)
464 {
465 std::string errorcode = Localization::GetInstance()->GetErrorDescription(errorId);
466 auto json = JsonUtil::Create(true);
467 json->Put("error", "");
468 auto param = json->ToString();
469 auto eventHub = GetEventHub<VideoEventHub>();
470 CHECK_NULL_VOID(eventHub);
471 eventHub->FireErrorEvent(param);
472 }
473
OnResolutionChange() const474 void VideoPattern::OnResolutionChange() const
475 {
476 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
477 return;
478 }
479 auto host = GetHost();
480 CHECK_NULL_VOID(host);
481 SizeF videoSize =
482 SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
483 auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
484 CHECK_NULL_VOID(videoLayoutProperty);
485 videoLayoutProperty->UpdateVideoSize(videoSize);
486 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
487 }
488
OnStartRenderFrameCb() const489 void VideoPattern::OnStartRenderFrameCb() const
490 {
491 auto host = GetHost();
492 CHECK_NULL_VOID(host);
493 auto video = AceType::DynamicCast<VideoNode>(host);
494 CHECK_NULL_VOID(video);
495 auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
496 CHECK_NULL_VOID(image);
497 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
498 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
499 image->MarkModifyDone();
500 }
501
OnPrepared(double width,double height,uint32_t duration,uint32_t currentPos,bool needFireEvent)502 void VideoPattern::OnPrepared(double width, double height, uint32_t duration, uint32_t currentPos, bool needFireEvent)
503 {
504 auto host = GetHost();
505 CHECK_NULL_VOID(host);
506 auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
507 CHECK_NULL_VOID(videoLayoutProperty);
508 CHECK_NULL_VOID(mediaPlayer_);
509 videoLayoutProperty->UpdateVideoSize(SizeF(static_cast<float>(width), static_cast<float>(height)));
510 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
511
512 duration_ = duration;
513 currentPos_ = currentPos;
514 isInitialState_ = currentPos != 0 ? false : isInitialState_;
515 isPlaying_ = mediaPlayer_->IsPlaying();
516 OnUpdateTime(duration_, DURATION_POS);
517 OnUpdateTime(currentPos_, CURRENT_POS);
518
519 RefPtr<UINode> controlBar = nullptr;
520 auto children = host->GetChildren();
521 for (const auto& child : children) {
522 if (child->GetTag() == V2::ROW_ETS_TAG) {
523 controlBar = child;
524 break;
525 }
526 }
527 CHECK_NULL_VOID(controlBar);
528 auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
529 auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
530 CHECK_NULL_VOID(sliderPaintProperty);
531 sliderPaintProperty->UpdateMin(0.0f);
532 sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
533 sliderNode->MarkModifyDone();
534 auto playBtn = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(0));
535 ChangePlayButtonTag(playBtn);
536
537 if (needFireEvent) {
538 auto json = JsonUtil::Create(true);
539 json->Put("duration", static_cast<double>(duration_));
540 auto param = json->ToString();
541 auto eventHub = GetEventHub<VideoEventHub>();
542 CHECK_NULL_VOID(eventHub);
543 eventHub->FirePreparedEvent(param);
544 }
545 UpdateLooping();
546 UpdateSpeed();
547 UpdateMuted();
548
549 checkNeedAutoPlay();
550 }
551
checkNeedAutoPlay()552 void VideoPattern::checkNeedAutoPlay()
553 {
554 if (isStop_) {
555 isStop_ = false;
556 Start();
557 }
558 if (dragEndAutoPlay_) {
559 dragEndAutoPlay_ = false;
560 Start();
561 }
562 if (autoPlay_) {
563 Start();
564 }
565 }
566
OnCompletion()567 void VideoPattern::OnCompletion()
568 {
569 isPlaying_ = false;
570 currentPos_ = duration_;
571 OnUpdateTime(currentPos_, CURRENT_POS);
572 auto json = JsonUtil::Create(true);
573 json->Put("finish", "");
574 auto param = json->ToString();
575 auto eventHub = GetEventHub<VideoEventHub>();
576 CHECK_NULL_VOID(eventHub);
577 eventHub->FireFinishEvent(param);
578 }
579
HasPlayer() const580 bool VideoPattern::HasPlayer() const
581 {
582 return mediaPlayer_ != nullptr;
583 }
584
HiddenChange(bool hidden)585 void VideoPattern::HiddenChange(bool hidden)
586 {
587 if (isPlaying_ && hidden && HasPlayer()) {
588 pastPlayingStatus_ = isPlaying_;
589 Pause();
590 return;
591 }
592
593 if (!hidden && pastPlayingStatus_) {
594 pastPlayingStatus_ = false;
595 Start();
596 }
597 }
598
OnVisibleChange(bool isVisible)599 void VideoPattern::OnVisibleChange(bool isVisible)
600 {
601 if (hiddenChangeEvent_) {
602 hiddenChangeEvent_(!isVisible);
603 }
604 }
605
UpdateLooping()606 void VideoPattern::UpdateLooping()
607 {
608 if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
609 ContainerScope scope(instanceId_);
610 auto context = PipelineContext::GetCurrentContext();
611 CHECK_NULL_VOID(context);
612 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
613 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), loop = loop_] {
614 auto mediaPlayer = weak.Upgrade();
615 CHECK_NULL_VOID(mediaPlayer);
616 mediaPlayer->SetLooping(loop);
617 });
618 }
619 }
620
UpdateSpeed()621 void VideoPattern::UpdateSpeed()
622 {
623 if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
624 ContainerScope scope(instanceId_);
625 auto context = PipelineContext::GetCurrentContext();
626 CHECK_NULL_VOID(context);
627 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
628 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), progress = progressRate_] {
629 auto mediaPlayer = weak.Upgrade();
630 CHECK_NULL_VOID(mediaPlayer);
631 mediaPlayer->SetPlaybackSpeed(static_cast<float>(progress));
632 });
633 }
634 }
635
UpdateMuted()636 void VideoPattern::UpdateMuted()
637 {
638 if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
639 ContainerScope scope(instanceId_);
640 float volume = muted_ ? 0.0f : 1.0f;
641 auto context = PipelineContext::GetCurrentContext();
642 CHECK_NULL_VOID(context);
643 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
644 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
645 auto mediaPlayer = weak.Upgrade();
646 CHECK_NULL_VOID(mediaPlayer);
647 mediaPlayer->SetVolume(videoVolume, videoVolume);
648 });
649 }
650 }
651
OnUpdateTime(uint32_t time,int pos) const652 void VideoPattern::OnUpdateTime(uint32_t time, int pos) const
653 {
654 auto host = GetHost();
655 CHECK_NULL_VOID(host);
656 auto layoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
657 CHECK_NULL_VOID(layoutProperty);
658 bool needControlBar = layoutProperty->GetControlsValue(true);
659 if (!needControlBar) {
660 return;
661 }
662
663 RefPtr<UINode> controlBar = nullptr;
664 auto children = host->GetChildren();
665 for (const auto& child : children) {
666 if (child->GetTag() == V2::ROW_ETS_TAG) {
667 controlBar = child;
668 break;
669 }
670 }
671
672 CHECK_NULL_VOID(controlBar);
673 auto durationNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(pos));
674 CHECK_NULL_VOID(durationNode);
675 auto textLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
676 CHECK_NULL_VOID(textLayoutProperty);
677 std::string timeText = IntTimeToText(time);
678 textLayoutProperty->UpdateContent(timeText);
679 durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
680 durationNode->MarkModifyDone();
681 if (pos == CURRENT_POS) {
682 auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
683 CHECK_NULL_VOID(sliderNode);
684 auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
685 CHECK_NULL_VOID(sliderPattern);
686 sliderPattern->UpdateValue(static_cast<float>(time));
687 sliderNode->MarkModifyDone();
688 }
689 }
690
PrepareSurface()691 void VideoPattern::PrepareSurface()
692 {
693 if (!mediaPlayer_ || renderSurface_->IsSurfaceValid()) {
694 return;
695 }
696 if (!SystemProperties::GetExtSurfaceEnabled()) {
697 renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
698 }
699 renderSurface_->InitSurface();
700 mediaPlayer_->SetRenderSurface(renderSurface_);
701 if (mediaPlayer_->SetSurface() != 0) {
702 TAG_LOGW(AceLogTag::ACE_VIDEO, "mediaPlayer renderSurface set failed");
703 }
704 }
705
OnAttachToFrameNode()706 void VideoPattern::OnAttachToFrameNode()
707 {
708 // full screen node is not supposed to register js controller event
709 if (!InstanceOf<VideoFullScreenPattern>(this)) {
710 SetMethodCall();
711 }
712 auto host = GetHost();
713 CHECK_NULL_VOID(host);
714 auto renderContext = host->GetRenderContext();
715 CHECK_NULL_VOID(renderContext);
716 static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
717 RenderContext::PatternType::VIDEO };
718 renderContextForMediaPlayer_->InitContext(false, param);
719
720 if (SystemProperties::GetExtSurfaceEnabled()) {
721 RegisterRenderContextCallBack();
722 }
723
724 renderContext->UpdateBackgroundColor(Color::BLACK);
725 renderContextForMediaPlayer_->UpdateBackgroundColor(Color::BLACK);
726 renderContext->SetClipToBounds(true);
727 }
728
OnDetachFromMainTree()729 void VideoPattern::OnDetachFromMainTree()
730 {
731 auto host = GetHost();
732 if (host && host->GetNodeStatus() == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
733 Pause();
734 }
735 }
736
RegisterRenderContextCallBack()737 void VideoPattern::RegisterRenderContextCallBack()
738 {
739 #ifndef VIDEO_TEXTURE_SUPPORTED
740 auto isFullScreen = IsFullScreen();
741 if (!isFullScreen) {
742 auto OnAreaChangedCallBack = [weak = WeakClaim(this)](float x, float y, float w, float h) mutable {
743 auto videoPattern = weak.Upgrade();
744 CHECK_NULL_VOID(videoPattern);
745 auto host = videoPattern->GetHost();
746 CHECK_NULL_VOID(host);
747 auto geometryNode = host->GetGeometryNode();
748 CHECK_NULL_VOID(geometryNode);
749 auto videoNodeSize = geometryNode->GetContentSize();
750 auto layoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
751 CHECK_NULL_VOID(layoutProperty);
752 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
753 Rect rect = Rect(x + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
754 y + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
755 videoFrameSize.Height());
756 if (videoPattern->renderSurface_) {
757 if (videoPattern->renderSurface_->SetExtSurfaceBoundsSync(
758 rect.Left(), rect.Top(), rect.Width(), rect.Height())) {
759 videoPattern->lastBoundsRect_ = rect;
760 }
761 }
762 };
763 renderContextForMediaPlayer_->SetSurfaceChangedCallBack(OnAreaChangedCallBack);
764 }
765 #else
766 renderSurfaceWeakPtr_ = renderSurface_;
767 renderContextForMediaPlayerWeakPtr_ = renderContextForMediaPlayer_;
768 auto OnAttachCallBack = [weak = WeakClaim(this)](int64_t textureId, bool isAttach) mutable {
769 LOGI("OnAttachCallBack.");
770 auto videoPattern = weak.Upgrade();
771 CHECK_NULL_VOID(videoPattern);
772 if (auto renderSurface = videoPattern->renderSurfaceWeakPtr_.Upgrade(); renderSurface) {
773 renderSurface->AttachToGLContext(textureId, isAttach);
774 }
775 };
776 renderContextForMediaPlayer_->AddAttachCallBack(OnAttachCallBack);
777 auto OnUpdateCallBack = [weak = WeakClaim(this)](std::vector<float>& matrix) mutable {
778 auto videoPattern = weak.Upgrade();
779 CHECK_NULL_VOID(videoPattern);
780 if (auto renderSurface = videoPattern->renderSurfaceWeakPtr_.Upgrade(); renderSurface) {
781 renderSurface->UpdateTextureImage(matrix);
782 }
783 };
784 renderContextForMediaPlayer_->AddUpdateCallBack(OnUpdateCallBack);
785 #endif
786 }
787
OnModifyDone()788 void VideoPattern::OnModifyDone()
789 {
790 Pattern::OnModifyDone();
791 if (!hiddenChangeEvent_) {
792 SetHiddenChangeEvent([weak = WeakClaim(this)](bool hidden) {
793 auto videoPattern = weak.Upgrade();
794 CHECK_NULL_VOID(videoPattern);
795 auto fullScreenNode = videoPattern->GetFullScreenNode();
796 if (fullScreenNode) {
797 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
798 CHECK_NULL_VOID(fullScreenPattern);
799 fullScreenPattern->HiddenChange(hidden);
800 return;
801 }
802 videoPattern->HiddenChange(hidden);
803 });
804 }
805
806 // update full screen pattern state
807 UpdateFsState();
808
809 // Update the control bar and preview image.
810 UpdatePreviewImage();
811 UpdateControllerBar();
812
813 // Update the media player when video node is not in full screen or current node is full screen node
814 if (!fullScreenNodeId_.has_value() || InstanceOf<VideoFullScreenNode>(this)) {
815 ContainerScope scope(instanceId_);
816 auto pipelineContext = PipelineContext::GetCurrentContext();
817 CHECK_NULL_VOID(pipelineContext);
818 auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI);
819 uiTaskExecutor.PostTask([weak = WeakClaim(this)]() {
820 auto videoPattern = weak.Upgrade();
821 CHECK_NULL_VOID(videoPattern);
822 ContainerScope scope(videoPattern->instanceId_);
823 videoPattern->UpdateMediaPlayerOnBg();
824 });
825 }
826
827 if (SystemProperties::GetExtSurfaceEnabled()) {
828 auto pipelineContext = PipelineContext::GetCurrentContext();
829 CHECK_NULL_VOID(pipelineContext);
830 auto host = GetHost();
831 CHECK_NULL_VOID(host);
832 pipelineContext->AddOnAreaChangeNode(host->GetId());
833 }
834 EnableDrag();
835 auto eventHub = GetEventHub<VideoEventHub>();
836 if (!AceType::InstanceOf<VideoFullScreenPattern>(this)) {
837 auto host = GetHost();
838 CHECK_NULL_VOID(host);
839 eventHub->SetInspectorId(host->GetInspectorIdValue(""));
840 }
841 }
842
UpdatePreviewImage()843 void VideoPattern::UpdatePreviewImage()
844 {
845 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
846 CHECK_NULL_VOID(layoutProperty);
847 if (!layoutProperty->HasPosterImageInfo()) {
848 return;
849 }
850 auto posterSourceInfo = layoutProperty->GetPosterImageInfo().value();
851 auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
852 auto host = GetHost();
853 CHECK_NULL_VOID(host);
854
855 auto video = AceType::DynamicCast<VideoNode>(host);
856 CHECK_NULL_VOID(video);
857 auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
858 CHECK_NULL_VOID(image);
859 if (!isInitialState_ || !layoutProperty->HasPosterImageInfo()) {
860 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
861 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
862 image->MarkModifyDone();
863 return;
864 }
865
866 if (!posterSourceInfo.IsValid()) {
867 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
868 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
869 image->MarkModifyDone();
870 TAG_LOGI(AceLogTag::ACE_VIDEO, "Src image is not valid.");
871 return;
872 }
873
874 if (image) {
875 image->SetDraggable(false);
876 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
877 posterLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
878 posterLayoutProperty->UpdateImageSourceInfo(posterSourceInfo);
879 posterLayoutProperty->UpdateImageFit(imageFit);
880 image->MarkModifyDone();
881 }
882 }
883
UpdateControllerBar()884 void VideoPattern::UpdateControllerBar()
885 {
886 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
887 CHECK_NULL_VOID(layoutProperty);
888 auto host = GetHost();
889 CHECK_NULL_VOID(host);
890 auto children = host->GetChildren();
891 if (layoutProperty->GetControlsValue(true)) {
892 auto video = AceType::DynamicCast<VideoNode>(host);
893 CHECK_NULL_VOID(video);
894 auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
895 if (controller) {
896 auto sliderNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(SLIDER_POS));
897 CHECK_NULL_VOID(sliderNode);
898 auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
899 CHECK_NULL_VOID(sliderPattern);
900 sliderPattern->UpdateValue(static_cast<float>(currentPos_));
901 sliderNode->MarkModifyDone();
902
903 auto textNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(CURRENT_POS));
904 CHECK_NULL_VOID(textNode);
905 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
906 CHECK_NULL_VOID(textLayoutProperty);
907 std::string label = IntTimeToText(currentPos_);
908 textLayoutProperty->UpdateContent(label);
909
910 auto durationNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(DURATION_POS));
911 CHECK_NULL_VOID(durationNode);
912 auto durationTextLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
913 CHECK_NULL_VOID(durationTextLayoutProperty);
914 std::string durationText = IntTimeToText(duration_);
915 durationTextLayoutProperty->UpdateContent(durationText);
916
917 textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
918 textNode->MarkModifyDone();
919 durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
920 durationNode->MarkModifyDone();
921 auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
922 controllerLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
923 controller->MarkModifyDone();
924 }
925 } else {
926 auto video = AceType::DynamicCast<VideoNode>(host);
927 CHECK_NULL_VOID(video);
928 auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
929 CHECK_NULL_VOID(controller);
930 if (controller) {
931 auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
932 controllerLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
933 controller->MarkModifyDone();
934 }
935 }
936 }
937
UpdateVideoProperty()938 void VideoPattern::UpdateVideoProperty()
939 {
940 if (isInitialState_ && autoPlay_) {
941 Start();
942 }
943
944 UpdateSpeed();
945 UpdateLooping();
946 UpdateMuted();
947 }
948
OnRebuildFrame()949 void VideoPattern::OnRebuildFrame()
950 {
951 if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
952 TAG_LOGW(AceLogTag::ACE_VIDEO, "MediaPlayer surface is not valid");
953 return;
954 }
955 auto host = GetHost();
956 CHECK_NULL_VOID(host);
957 auto video = AceType::DynamicCast<VideoNode>(host);
958 CHECK_NULL_VOID(video);
959 auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
960 CHECK_NULL_VOID(column);
961 auto renderContext = column->GetRenderContext();
962 renderContext->AddChild(renderContextForMediaPlayer_, 0);
963 }
964
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)965 bool VideoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
966 {
967 if (config.skipMeasure || dirty->SkipMeasureContent()) {
968 return false;
969 }
970 auto geometryNode = dirty->GetGeometryNode();
971 CHECK_NULL_RETURN(geometryNode, false);
972 auto videoNodeSize = geometryNode->GetContentSize();
973 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
974 CHECK_NULL_RETURN(layoutProperty, false);
975 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
976 // Change the surface layout for drawing video frames
977 if (renderContextForMediaPlayer_) {
978 renderContextForMediaPlayer_->SetBounds((videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
979 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
980 videoFrameSize.Height());
981 }
982 auto host = GetHost();
983 CHECK_NULL_RETURN(host, false);
984 host->MarkNeedSyncRenderTree();
985 auto video = AceType::DynamicCast<VideoNode>(host);
986 CHECK_NULL_RETURN(video, false);
987 auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
988 CHECK_NULL_RETURN(column, false);
989 column->GetRenderContext()->SetClipToBounds(true);
990 return false;
991 }
992
OnAreaChangedInner()993 void VideoPattern::OnAreaChangedInner()
994 {
995 #ifndef VIDEO_TEXTURE_SUPPORTED
996 auto isFullScreen = IsFullScreen();
997 if (SystemProperties::GetExtSurfaceEnabled() && isFullScreen) {
998 #else
999 if (SystemProperties::GetExtSurfaceEnabled()) {
1000 #endif
1001 auto host = GetHost();
1002 CHECK_NULL_VOID(host);
1003 auto geometryNode = host->GetGeometryNode();
1004 CHECK_NULL_VOID(geometryNode);
1005 auto videoNodeSize = geometryNode->GetContentSize();
1006 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1007 CHECK_NULL_VOID(layoutProperty);
1008 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
1009 auto transformRelativeOffset = host->GetTransformRelativeOffset();
1010
1011 Rect rect =
1012 Rect(transformRelativeOffset.GetX() + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
1013 transformRelativeOffset.GetY() + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE,
1014 videoFrameSize.Width(), videoFrameSize.Height());
1015 if (renderSurface_ && (rect != lastBoundsRect_)) {
1016 renderSurface_->SetExtSurfaceBounds(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1017 lastBoundsRect_ = rect;
1018 }
1019 }
1020 }
1021
1022 void VideoPattern::OnColorConfigurationUpdate()
1023 {
1024 ContainerScope scope(instanceId_);
1025 auto host = GetHost();
1026 CHECK_NULL_VOID(host);
1027 auto pipelineContext = PipelineBase::GetCurrentContext();
1028 CHECK_NULL_VOID(pipelineContext);
1029 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1030 CHECK_NULL_VOID(videoTheme);
1031 auto renderContext = controlBar_->GetRenderContext();
1032 CHECK_NULL_VOID(renderContext);
1033 renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
1034 for (const auto& child : controlBar_->GetChildren()) {
1035 if (child->GetTag() == V2::TEXT_ETS_TAG) {
1036 auto frameNode = AceType::DynamicCast<FrameNode>(child);
1037 if (frameNode) {
1038 auto textLayoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
1039 if (textLayoutProperty) {
1040 auto textStyle = videoTheme->GetTimeTextStyle();
1041 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
1042 }
1043 }
1044 }
1045 }
1046 host->SetNeedCallChildrenUpdate(false);
1047 host->MarkModifyDone();
1048 host->MarkDirtyNode();
1049 }
1050
1051 bool VideoPattern::NeedLift() const
1052 {
1053 auto host = GetHost();
1054 CHECK_NULL_RETURN(host, false);
1055 auto renderContext = host->GetRenderContext();
1056 CHECK_NULL_RETURN(renderContext, false);
1057 return IsFullScreen() && renderContext->IsUniRenderEnabled();
1058 }
1059
1060 RefPtr<FrameNode> VideoPattern::CreateControlBar(int32_t nodeId)
1061 {
1062 ContainerScope scope(instanceId_);
1063 auto pipelineContext = PipelineBase::GetCurrentContext();
1064 CHECK_NULL_RETURN(pipelineContext, nullptr);
1065 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1066 CHECK_NULL_RETURN(videoTheme, nullptr);
1067 auto controlBar = FrameNode::GetOrCreateFrameNode(
1068 V2::ROW_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1069 CHECK_NULL_RETURN(controlBar, nullptr);
1070 controlBar_ = controlBar;
1071
1072 auto playButton = CreateSVG();
1073 CHECK_NULL_RETURN(playButton, nullptr);
1074 ChangePlayButtonTag(playButton);
1075 controlBar->AddChild(playButton);
1076
1077 auto currentPosText = CreateText(currentPos_);
1078 CHECK_NULL_RETURN(currentPosText, nullptr);
1079 controlBar->AddChild(currentPosText);
1080
1081 auto slider = CreateSlider();
1082 CHECK_NULL_RETURN(currentPosText, nullptr);
1083 controlBar->AddChild(slider);
1084
1085 auto durationText = CreateText(duration_);
1086 CHECK_NULL_RETURN(durationText, nullptr);
1087 controlBar->AddChild(durationText);
1088
1089 auto fullScreenButton = CreateSVG();
1090 CHECK_NULL_RETURN(fullScreenButton, nullptr);
1091 SetFullScreenButtonCallBack(fullScreenButton);
1092 ChangeFullScreenButtonTag(InstanceOf<VideoFullScreenNode>(this), fullScreenButton);
1093 controlBar->AddChild(fullScreenButton);
1094
1095 auto renderContext = controlBar->GetRenderContext();
1096 renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
1097 auto controlBarLayoutProperty = controlBar->GetLayoutProperty<LinearLayoutProperty>();
1098 controlBarLayoutProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
1099 if (NeedLift()) {
1100 PaddingProperty padding;
1101 padding.bottom = CalcLength(LIFT_HEIGHT);
1102 controlBarLayoutProperty->UpdatePadding(padding);
1103 }
1104 return controlBar;
1105 }
1106
1107 RefPtr<FrameNode> VideoPattern::CreateSlider()
1108 {
1109 auto pipelineContext = PipelineBase::GetCurrentContext();
1110 CHECK_NULL_RETURN(pipelineContext, nullptr);
1111 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1112 CHECK_NULL_RETURN(videoTheme, nullptr);
1113
1114 auto sliderNode = FrameNode::CreateFrameNode(V2::SLIDER_ETS_TAG, -1, AceType::MakeRefPtr<SliderPattern>());
1115 CHECK_NULL_RETURN(sliderNode, nullptr);
1116 auto sliderLayoutProperty = sliderNode->GetLayoutProperty<SliderLayoutProperty>();
1117 CHECK_NULL_RETURN(sliderLayoutProperty, nullptr);
1118
1119 auto sliderEdge = videoTheme->GetSliderEdge();
1120 PaddingProperty padding;
1121 padding.left = CalcLength(sliderEdge.Left());
1122 padding.right = CalcLength(sliderEdge.Right());
1123 padding.top = CalcLength(sliderEdge.Top());
1124 padding.bottom = CalcLength(sliderEdge.Bottom());
1125 sliderLayoutProperty->UpdatePadding(padding);
1126 sliderLayoutProperty->UpdateLayoutWeight(1.0);
1127
1128 SliderOnChangeEvent sliderOnChangeEvent = [weak = WeakClaim(this)](float value, int32_t mode) {
1129 auto videoPattern = weak.Upgrade();
1130 CHECK_NULL_VOID(videoPattern);
1131 videoPattern->OnSliderChange(value, mode);
1132 };
1133 auto sliderEventHub = sliderNode->GetEventHub<SliderEventHub>();
1134 sliderEventHub->SetOnChange(std::move(sliderOnChangeEvent));
1135
1136 auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
1137 CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
1138 sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
1139 sliderPaintProperty->UpdateSelectColor(Color::BLACK);
1140 sliderPaintProperty->UpdateValue(static_cast<float>(currentPos_));
1141 sliderNode->MarkModifyDone();
1142 return sliderNode;
1143 }
1144
1145 RefPtr<FrameNode> VideoPattern::CreateText(uint32_t time)
1146 {
1147 auto pipelineContext = PipelineBase::GetCurrentContext();
1148 CHECK_NULL_RETURN(pipelineContext, nullptr);
1149 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1150 CHECK_NULL_RETURN(videoTheme, nullptr);
1151
1152 auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<TextPattern>());
1153 CHECK_NULL_RETURN(textNode, nullptr);
1154 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1155 CHECK_NULL_RETURN(textLayoutProperty, nullptr);
1156 auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1157 CHECK_NULL_RETURN(videoLayoutProperty, nullptr);
1158 std::string label = "";
1159 if (videoLayoutProperty->GetControlsValue(true)) {
1160 label = IntTimeToText(time);
1161 }
1162 textLayoutProperty->UpdateContent(label);
1163 auto textEdge = videoTheme->GetTextEdge();
1164 PaddingProperty padding;
1165 padding.left = CalcLength(textEdge.Left());
1166 padding.right = CalcLength(textEdge.Right());
1167 padding.top = CalcLength(textEdge.Top());
1168 padding.bottom = CalcLength(textEdge.Bottom());
1169 textLayoutProperty->UpdatePadding(padding);
1170 auto textStyle = videoTheme->GetTimeTextStyle();
1171 textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
1172 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
1173 return textNode;
1174 }
1175
1176 RefPtr<FrameNode> VideoPattern::CreateSVG()
1177 {
1178 auto pipelineContext = PipelineBase::GetCurrentContext();
1179 CHECK_NULL_RETURN(pipelineContext, nullptr);
1180 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1181 CHECK_NULL_RETURN(videoTheme, nullptr);
1182
1183 auto svgNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
1184 CHECK_NULL_RETURN(svgNode, nullptr);
1185 auto svgLayoutProperty = svgNode->GetLayoutProperty<ImageLayoutProperty>();
1186
1187 auto btnEdge = videoTheme->GetBtnEdge();
1188 PaddingProperty padding;
1189 padding.left = CalcLength(btnEdge.Left());
1190 padding.right = CalcLength(btnEdge.Right());
1191 padding.top = CalcLength(btnEdge.Top());
1192 padding.bottom = CalcLength(btnEdge.Bottom());
1193 svgLayoutProperty->UpdatePadding(padding);
1194
1195 auto btnSize = videoTheme->GetBtnSize();
1196 SizeF size { static_cast<float>(btnSize.Width()), static_cast<float>(btnSize.Height()) };
1197 svgLayoutProperty->UpdateMarginSelfIdealSize(size);
1198 auto width = Dimension(btnSize.Width(), DimensionUnit::VP).ConvertToPx();
1199 auto height = Dimension(btnSize.Height(), DimensionUnit::VP).ConvertToPx();
1200 CalcSize idealSize = { CalcLength(width), CalcLength(height) };
1201 MeasureProperty layoutConstraint;
1202 layoutConstraint.selfIdealSize = idealSize;
1203 layoutConstraint.maxSize = idealSize;
1204 svgNode->UpdateLayoutConstraint(layoutConstraint);
1205 return svgNode;
1206 }
1207
1208 void VideoPattern::SetMethodCall()
1209 {
1210 ContainerScope scope(instanceId_);
1211 auto videoController = AceType::MakeRefPtr<VideoController>();
1212 auto context = PipelineContext::GetCurrentContext();
1213 CHECK_NULL_VOID(context);
1214 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1215 videoController->SetStartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1216 uiTaskExecutor.PostTask([weak]() {
1217 auto pattern = weak.Upgrade();
1218 CHECK_NULL_VOID(pattern);
1219 ContainerScope scope(pattern->instanceId_);
1220 auto targetPattern = pattern->GetTargetVideoPattern();
1221 CHECK_NULL_VOID(targetPattern);
1222 targetPattern->Start();
1223 });
1224 });
1225 videoController->SetPausetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1226 uiTaskExecutor.PostTask([weak]() {
1227 auto pattern = weak.Upgrade();
1228 CHECK_NULL_VOID(pattern);
1229 ContainerScope scope(pattern->instanceId_);
1230 auto targetPattern = pattern->GetTargetVideoPattern();
1231 CHECK_NULL_VOID(targetPattern);
1232 targetPattern->Pause();
1233 });
1234 });
1235 videoController->SetStopImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1236 uiTaskExecutor.PostTask([weak]() {
1237 auto pattern = weak.Upgrade();
1238 CHECK_NULL_VOID(pattern);
1239 ContainerScope scope(pattern->instanceId_);
1240 auto targetPattern = pattern->GetTargetVideoPattern();
1241 CHECK_NULL_VOID(targetPattern);
1242 targetPattern->Stop();
1243 });
1244 });
1245 videoController->SetSeekToImpl([weak = WeakClaim(this), uiTaskExecutor](float pos, SeekMode seekMode) {
1246 uiTaskExecutor.PostTask([weak, pos, seekMode]() {
1247 auto pattern = weak.Upgrade();
1248 CHECK_NULL_VOID(pattern);
1249 ContainerScope scope(pattern->instanceId_);
1250 auto targetPattern = pattern->GetTargetVideoPattern();
1251 CHECK_NULL_VOID(targetPattern);
1252 targetPattern->SetCurrentTime(pos, seekMode);
1253 });
1254 });
1255 videoController->SetRequestFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isFullScreen) {
1256 uiTaskExecutor.PostTask([weak, isFullScreen]() {
1257 auto videoPattern = weak.Upgrade();
1258 CHECK_NULL_VOID(videoPattern);
1259 ContainerScope scope(videoPattern->instanceId_);
1260 if (isFullScreen) {
1261 videoPattern->FullScreen();
1262 } else {
1263 videoPattern->ResetLastBoundsRect();
1264 auto targetPattern = videoPattern->GetTargetVideoPattern();
1265 CHECK_NULL_VOID(targetPattern);
1266 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1267 CHECK_NULL_VOID(fullScreenPattern);
1268 fullScreenPattern->ExitFullScreen();
1269 }
1270 });
1271 });
1272 videoController->SetExitFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isSync) {
1273 if (isSync) {
1274 auto pattern = weak.Upgrade();
1275 CHECK_NULL_VOID(pattern);
1276 auto targetPattern = pattern->GetTargetVideoPattern();
1277 CHECK_NULL_VOID(targetPattern);
1278 pattern->ResetLastBoundsRect();
1279 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1280 fullScreenPattern->ExitFullScreen();
1281 return;
1282 }
1283 uiTaskExecutor.PostTask([weak]() {
1284 auto pattern = weak.Upgrade();
1285 CHECK_NULL_VOID(pattern);
1286 ContainerScope scope(pattern->instanceId_);
1287 pattern->ResetLastBoundsRect();
1288 auto targetPattern = pattern->GetTargetVideoPattern();
1289 CHECK_NULL_VOID(targetPattern);
1290 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1291 CHECK_NULL_VOID(fullScreenPattern);
1292 fullScreenPattern->ExitFullScreen();
1293 });
1294 });
1295 CHECK_NULL_VOID(videoControllerV2_);
1296 videoControllerV2_->AddVideoController(videoController);
1297 }
1298
1299 void VideoPattern::Start()
1300 {
1301 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1302 return;
1303 }
1304
1305 if (isStop_ && mediaPlayer_->PrepareAsync() != 0) {
1306 TAG_LOGW(AceLogTag::ACE_VIDEO, "Player has not prepared");
1307 return;
1308 }
1309 ContainerScope scope(instanceId_);
1310 auto context = PipelineContext::GetCurrentContext();
1311 CHECK_NULL_VOID(context);
1312
1313 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1314 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_))] {
1315 auto mediaPlayer = weak.Upgrade();
1316 CHECK_NULL_VOID(mediaPlayer);
1317 TAG_LOGI(AceLogTag::ACE_VIDEO, "trigger mediaPlayer play");
1318 mediaPlayer->Play();
1319 });
1320 }
1321
1322 void VideoPattern::Pause()
1323 {
1324 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1325 return;
1326 }
1327 mediaPlayer_->Pause();
1328 }
1329
1330 void VideoPattern::Stop()
1331 {
1332 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1333 return;
1334 }
1335
1336 OnCurrentTimeChange(0);
1337 mediaPlayer_->Stop();
1338 isStop_ = true;
1339 }
1340
1341 void VideoPattern::FireError()
1342 {
1343 ContainerScope scope(instanceId_);
1344 auto context = PipelineContext::GetCurrentContext();
1345 CHECK_NULL_VOID(context);
1346
1347 // OnError function must be excuted on ui, so get the uiTaskExecutor.
1348 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1349 uiTaskExecutor.PostTask([weak = WeakClaim(this)] {
1350 auto videoPattern = weak.Upgrade();
1351 CHECK_NULL_VOID(videoPattern);
1352 ContainerScope scope(videoPattern->instanceId_);
1353 videoPattern->OnError("");
1354 });
1355 }
1356
1357 void VideoPattern::ChangePlayButtonTag()
1358 {
1359 ContainerScope scope(instanceId_);
1360 auto context = PipelineContext::GetCurrentContext();
1361 CHECK_NULL_VOID(context);
1362 auto host = GetHost();
1363 CHECK_NULL_VOID(host);
1364 const auto& children = host->GetChildren();
1365 for (const auto& child : children) {
1366 if (child->GetTag() == V2::ROW_ETS_TAG) {
1367 auto playBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(0));
1368 ChangePlayButtonTag(playBtn);
1369 break;
1370 }
1371 }
1372 }
1373
1374 void VideoPattern::ChangePlayButtonTag(RefPtr<FrameNode>& playBtn)
1375 {
1376 CHECK_NULL_VOID(playBtn);
1377 auto playClickCallback = [weak = WeakClaim(this), playing = isPlaying_](GestureEvent& /* info */) {
1378 auto videoPattern = weak.Upgrade();
1379 CHECK_NULL_VOID(videoPattern);
1380 if (playing) {
1381 videoPattern->Pause();
1382 } else {
1383 videoPattern->Start();
1384 }
1385 };
1386 auto playBtnEvent = playBtn->GetOrCreateGestureEventHub();
1387 playBtnEvent->SetUserOnClick(std::move(playClickCallback));
1388 auto svgLayoutProperty = playBtn->GetLayoutProperty<ImageLayoutProperty>();
1389 auto resourceId = isPlaying_ ? InternalResource::ResourceId::PAUSE_SVG : InternalResource::ResourceId::PLAY_SVG;
1390 auto svgSourceInfo = ImageSourceInfo("");
1391 svgSourceInfo.SetResourceId(resourceId);
1392 svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1393 playBtn->MarkModifyDone();
1394 playBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1395 }
1396
1397 void VideoPattern::SetFullScreenButtonCallBack(RefPtr<FrameNode>& fullScreenBtn)
1398 {
1399 CHECK_NULL_VOID(fullScreenBtn);
1400 auto fsClickCallback = [weak = WeakClaim(this)](GestureEvent& /* info */) {
1401 auto videoPattern = weak.Upgrade();
1402 CHECK_NULL_VOID(videoPattern);
1403 if (InstanceOf<VideoFullScreenPattern>(videoPattern)) {
1404 auto pattern = AceType::DynamicCast<VideoFullScreenPattern>(videoPattern);
1405 CHECK_NULL_VOID(pattern);
1406 videoPattern->ResetLastBoundsRect();
1407 pattern->ExitFullScreen();
1408 } else {
1409 videoPattern->FullScreen();
1410 }
1411 };
1412 auto fullScreenBtnEvent = fullScreenBtn->GetOrCreateGestureEventHub();
1413 fullScreenBtnEvent->SetUserOnClick(std::move(fsClickCallback));
1414 }
1415
1416 void VideoPattern::ChangeFullScreenButtonTag(bool isFullScreen, RefPtr<FrameNode>& fullScreenBtn)
1417 {
1418 CHECK_NULL_VOID(fullScreenBtn);
1419 auto svgLayoutProperty = fullScreenBtn->GetLayoutProperty<ImageLayoutProperty>();
1420 auto resourceId =
1421 isFullScreen ? InternalResource::ResourceId::QUIT_FULLSCREEN_SVG : InternalResource::ResourceId::FULLSCREEN_SVG;
1422 auto svgSourceInfo = ImageSourceInfo("");
1423 svgSourceInfo.SetResourceId(resourceId);
1424 svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1425 fullScreenBtn->MarkModifyDone();
1426 fullScreenBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1427 }
1428
1429 void VideoPattern::SetCurrentTime(float currentPos, OHOS::Ace::SeekMode seekMode)
1430 {
1431 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1432 return;
1433 }
1434 if (GreatOrEqual(currentPos, 0.0)) {
1435 mediaPlayer_->Seek(static_cast<int32_t>(currentPos * MILLISECONDS_TO_SECONDS), seekMode);
1436 }
1437 }
1438
1439 void VideoPattern::OnSliderChange(float posTime, int32_t mode)
1440 {
1441 SetCurrentTime(posTime, OHOS::Ace::SeekMode::SEEK_CLOSEST);
1442 auto eventHub = GetEventHub<VideoEventHub>();
1443 CHECK_NULL_VOID(eventHub);
1444 auto json = JsonUtil::Create(true);
1445 json->Put("time", static_cast<double>(posTime));
1446 auto param = json->ToString();
1447 CHECK_NULL_VOID(eventHub);
1448 if (mode == SliderChangeMode::BEGIN || mode == SliderChangeMode::MOVING) {
1449 eventHub->FireSeekingEvent(param);
1450 } else if (mode == SliderChangeMode::END) {
1451 eventHub->FireSeekedEvent(param);
1452 }
1453 }
1454
1455 void VideoPattern::OnFullScreenChange(bool isFullScreen)
1456 {
1457 auto json = JsonUtil::Create(true);
1458 json->Put("fullscreen", isFullScreen);
1459 auto param = json->ToString();
1460 auto eventHub = GetEventHub<VideoEventHub>();
1461 CHECK_NULL_VOID(eventHub);
1462 eventHub->FireFullScreenChangeEvent(param);
1463 auto host = GetHost();
1464 CHECK_NULL_VOID(host);
1465 const auto& children = host->GetChildren();
1466 for (const auto& child : children) {
1467 if (child->GetTag() == V2::ROW_ETS_TAG) {
1468 auto fsBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(FULL_SCREEN_POS));
1469 ChangeFullScreenButtonTag(isFullScreen, fsBtn);
1470 break;
1471 }
1472 }
1473 if (!SystemProperties::GetExtSurfaceEnabled()) {
1474 return;
1475 }
1476 if (!fullScreenNodeId_.has_value()) {
1477 SetMediaFullScreen(isFullScreen);
1478 return;
1479 }
1480 auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1481 CHECK_NULL_VOID(fullScreenNode);
1482 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
1483 CHECK_NULL_VOID(fullScreenPattern);
1484 fullScreenPattern->SetMediaFullScreen(isFullScreen);
1485 }
1486
1487 void VideoPattern::FullScreen()
1488 {
1489 if (fullScreenNodeId_.has_value()) {
1490 return;
1491 }
1492 ResetLastBoundsRect();
1493 auto host = GetHost();
1494 CHECK_NULL_VOID(host);
1495 auto videoNode = AceType::DynamicCast<VideoNode>(host);
1496 CHECK_NULL_VOID(videoNode);
1497 auto fullScreenPattern = AceType::MakeRefPtr<VideoFullScreenPattern>(videoControllerV2_);
1498 fullScreenPattern->InitFullScreenParam(
1499 AceType::Claim(this), renderSurface_, mediaPlayer_, renderContextForMediaPlayer_);
1500 fullScreenNodeId_ = ElementRegister::GetInstance()->MakeUniqueId();
1501 auto fullScreenNode =
1502 VideoFullScreenNode::CreateFullScreenNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value(), fullScreenPattern);
1503 CHECK_NULL_VOID(fullScreenNode);
1504 fullScreenPattern->RequestFullScreen(videoNode);
1505 }
1506
1507 void VideoPattern::EnableDrag()
1508 {
1509 auto host = GetHost();
1510 CHECK_NULL_VOID(host);
1511 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1512 auto dragEnd = [wp = WeakClaim(this)](
1513 const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1514 auto videoPattern = wp.Upgrade();
1515 CHECK_NULL_VOID(videoPattern);
1516 auto videoLayoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
1517 CHECK_NULL_VOID(videoLayoutProperty);
1518 CHECK_NULL_VOID(event);
1519 auto unifiedData = event->GetData();
1520 std::string videoSrc;
1521 if (unifiedData != nullptr) {
1522 int ret = UdmfClient::GetInstance()->GetVideoRecordUri(unifiedData, videoSrc);
1523 if (ret != 0) {
1524 TAG_LOGW(AceLogTag::ACE_VIDEO, "unifiedRecords is empty");
1525 return;
1526 }
1527 } else {
1528 auto json = JsonUtil::ParseJsonString(extraParams);
1529 std::string key = "extraInfo";
1530 videoSrc = json->GetString(key);
1531 }
1532
1533 if (videoSrc == videoPattern->GetSrc()) {
1534 return;
1535 }
1536
1537 videoPattern->SetIsDragEndAutoPlay(true);
1538 videoLayoutProperty->UpdateVideoSource(videoSrc);
1539 auto frameNode = videoPattern->GetHost();
1540 CHECK_NULL_VOID(frameNode);
1541 frameNode->MarkModifyDone();
1542 };
1543 auto eventHub = host->GetEventHub<EventHub>();
1544 CHECK_NULL_VOID(eventHub);
1545 eventHub->SetOnDrop(std::move(dragEnd));
1546 }
1547
1548 VideoPattern::~VideoPattern()
1549 {
1550 if (renderContextForMediaPlayer_) {
1551 renderContextForMediaPlayer_->RemoveSurfaceChangedCallBack();
1552 }
1553 if (!fullScreenNodeId_.has_value()) {
1554 return;
1555 }
1556 auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1557 CHECK_NULL_VOID(fullScreenNode);
1558 auto parent = fullScreenNode->GetParent();
1559 CHECK_NULL_VOID(parent);
1560 parent->RemoveChild(fullScreenNode);
1561 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1562 }
1563
1564 void VideoPattern::RecoverState(const RefPtr<VideoPattern>& videoPattern)
1565 {
1566 CHECK_NULL_VOID(videoPattern);
1567 currentPos_ = videoPattern->GetCurrentPos();
1568 if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid() && mediaPlayer_->IsPlaying() != isPlaying_) {
1569 isPlaying_ = mediaPlayer_->IsPlaying();
1570 ChangePlayButtonTag();
1571 }
1572 isInitialState_ = videoPattern->GetInitialState();
1573 auto layoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
1574 src_ = layoutProperty->GetVideoSourceValue("");
1575 isStop_ = videoPattern->GetIsStop();
1576 muted_ = videoPattern->GetMuted();
1577 autoPlay_ = videoPattern->GetAutoPlay();
1578 loop_ = videoPattern->GetLoop();
1579 duration_ = videoPattern->GetDuration();
1580 progressRate_ = videoPattern->GetProgressRate();
1581 fullScreenNodeId_.reset();
1582 RegisterMediaPlayerEvent();
1583 auto videoNode = GetHost();
1584 CHECK_NULL_VOID(videoNode);
1585 // change event hub to the origin video node
1586 videoPattern->GetEventHub<VideoEventHub>()->AttachHost(videoNode);
1587 videoNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1588 }
1589
1590 void VideoPattern::UpdateFsState()
1591 {
1592 if (!fullScreenNodeId_.has_value()) {
1593 return;
1594 }
1595 auto videoNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1596 CHECK_NULL_VOID(videoNode);
1597 auto videoPattern = AceType::DynamicCast<VideoFullScreenPattern>(videoNode->GetPattern());
1598 CHECK_NULL_VOID(videoPattern);
1599 // update full screen state
1600 videoPattern->UpdateState();
1601 }
1602
1603 bool VideoPattern::IsFullScreen() const
1604 {
1605 return fullScreenNodeId_.has_value();
1606 }
1607
1608 RefPtr<VideoPattern> VideoPattern::GetTargetVideoPattern()
1609 {
1610 auto isFullScreen = IsFullScreen();
1611 auto patternIsFullScreen = AceType::InstanceOf<VideoFullScreenPattern>(this);
1612 if ((isFullScreen && patternIsFullScreen) || (!isFullScreen && !patternIsFullScreen)) {
1613 return AceType::Claim(this);
1614 }
1615 if (patternIsFullScreen) {
1616 // current is full screen,need to be released
1617 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(this);
1618 return fullScreenPattern->GetVideoPattern();
1619 }
1620 // current node is origin video node, need to operate full screen node
1621 auto fullScreenNode = GetFullScreenNode();
1622 CHECK_NULL_RETURN(fullScreenNode, nullptr);
1623 return fullScreenNode->GetPattern<VideoPattern>();
1624 }
1625 } // namespace OHOS::Ace::NG
1626