1/* 2 * Copyright (c) 2020 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 "player_ability_slice.h" 17#include <algorithm> 18#include <vector> 19 20#include "ability_env.h" 21#include "ability_manager.h" 22#include "components/ui_image_view.h" 23#include "gfx_utils/file.h" 24 25using OHOS::Media::Player; 26using OHOS::Media::Source; 27using namespace OHOS::Media; 28 29namespace OHOS { 30REGISTER_AS(PlayerAbilitySlice) 31 32 33PlayerAbilitySlice::~PlayerAbilitySlice() 34{ 35 printf("################ ~PlayerAbilitySlice enter\n"); 36 37 /** released in DestoryPlayer(). */ 38 39 printf("################ ~PlayerAbilitySlice exit\n"); 40} 41 42std::shared_ptr<Player> PlayerAbilitySlice::CreatePlayer() 43{ 44 static std::shared_ptr<Player> instance_ = nullptr; 45 if (instance_ == nullptr) { 46 instance_ = std::make_shared<Player>(); 47 } 48 return instance_; 49} 50 51void PlayerAbilitySlice::Clear() 52{ 53 printf("PlayerAbilitySlice::Clear | enter\n"); 54 if (backIconListener_ != nullptr) { 55 delete backIconListener_; 56 backIconListener_ = nullptr; 57 } 58 if (onClickListener_ != nullptr) { 59 delete onClickListener_; 60 onClickListener_ = nullptr; 61 } 62 if (surfaceView_ != nullptr) { 63 delete surfaceView_; 64 surfaceView_ = nullptr; 65 } 66 if (animatorGroup_ != nullptr) { 67 delete animatorGroup_; 68 animatorGroup_ = nullptr; 69 } 70 if (backIcon_ != nullptr) { 71 delete backIcon_; 72 backIcon_ = nullptr; 73 } 74 if (backArea_ != nullptr) { 75 delete backArea_; 76 backArea_ = nullptr; 77 } 78 if (errorTips_ != nullptr) { 79 delete errorTips_; 80 errorTips_ = nullptr; 81 } 82 if (totalTimeLabel_ != nullptr) { 83 delete totalTimeLabel_; 84 totalTimeLabel_ = nullptr; 85 } 86 if (currentTimeLabel_ != nullptr) { 87 delete currentTimeLabel_; 88 currentTimeLabel_ = nullptr; 89 } 90 if (slider_ != nullptr) { 91 delete slider_; 92 slider_ = nullptr; 93 } 94 if (toggleButton_ != nullptr) { 95 delete toggleButton_; 96 toggleButton_ = nullptr; 97 } 98 if (toggleButtonArea_ != nullptr) { 99 delete toggleButtonArea_; 100 toggleButtonArea_ = nullptr; 101 } 102 if (rootView_ != nullptr) { 103 RootView::DestroyWindowRootView(rootView_); 104 rootView_ = nullptr; 105 } 106 printf("PlayerAbilitySlice::Clear() | end\n"); 107} 108 109void PlayerAbilitySlice::ShowErrorTips() 110{ 111 errorTips_ = new UILabel(); 112 errorTips_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y, ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT); 113 errorTips_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER, 114 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); 115 errorTips_->SetFont(FONT_NAME, GALLERY_FONT_SIZE); 116 errorTips_->SetText("视频播放错误"); 117 118 rootView_->Add(backArea_); 119 rootView_->Add(errorTips_); 120 rootView_->Add(backIcon_); 121 SetUIContent(rootView_); 122} 123 124void PlayerAbilitySlice::SetUpRootView() 125{ 126 if (rootView_ != nullptr) { 127 return; 128 } 129 rootView_ = RootView::GetWindowRootView(); 130 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y); 131 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT); 132 rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full); 133} 134 135void PlayerAbilitySlice::SetUpBackArea(const char* pathHeader) 136{ 137 auto onClick = [this] (UIView &view, const Event &event) -> bool { 138 printf("############ PlayerAbilitySlice terminate AS enter #############\n"); 139 Terminate(); 140 printf("############ PlayerAbilitySlice terminate AS exit #############\n"); 141 return true; 142 }; 143 backIcon_ = new UIImageView(); 144 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y); 145 146 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) { 147 printf("PlayerAbilitySlice::OnStart | backIconAbsolutePath | %s\n", pathHeader); 148 return; 149 } 150 backIcon_->SetSrc(backIconAbsolutePath); 151 backIcon_->SetTouchable(true); 152 backIconListener_ = new EventListener(onClick, nullptr); 153 backIcon_->SetOnClickListener(backIconListener_); 154 155 backArea_ = new UIViewGroup(); 156 backArea_->SetPosition(0, 0, LABEL_POSITION_X, LABEL_HEIGHT); 157 backArea_->SetStyle(STYLE_BACKGROUND_OPA, 0); 158 backArea_->SetTouchable(true); 159 backArea_->SetOnClickListener(backIconListener_); 160 161 rootView_->Add(backArea_); 162 rootView_->Add(backIcon_); 163} 164 165void PlayerAbilitySlice::SetUpVideoPlayer(const Want &want) 166{ 167 if (videoPlayer_ == nullptr) { 168 videoPlayer_ = new PlayerAdapter(); 169 } 170 videoPlayer_->sourceType = 1; 171 172 uint16_t videoPathLen = strlen(VIDEO_SOURCE_DIRECTORY) + strlen(reinterpret_cast<char*>(want.data)) + 1; 173 int8_t ret = sprintf_s(videoPlayer_->filePath, videoPathLen + 1, "%s/%s", VIDEO_SOURCE_DIRECTORY, 174 reinterpret_cast<char*>(want.data)); 175 if (ret < 0) { 176 printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath | %s\n", reinterpret_cast<char*>(want.data)); 177 return; 178 } 179 ret = sprintf_s(&videoPlayer_->filePath[videoPathLen - strlen(AVAILABEL_SOURCE_TYPE)], 180 strlen(AVAILABEL_SOURCE_TYPE) + 1, "%s", AVAILABEL_SOURCE_TYPE); 181 if (ret < 0) { 182 printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath \n"); 183 return; 184 } 185 printf("------########### mp4 file path | %s\n", videoPlayer_->filePath); 186 187 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer(); 188 std::string uri(videoPlayer_->filePath); 189 std::map<std::string, std::string> header; 190 Source source(uri, header); 191 videoPlayer_->adapter->SetSource(source); 192} 193 194bool PlayerAbilitySlice::SetUpSurfaceView() 195{ 196 if (surfaceView_ != nullptr) { 197 return true; 198 } 199 int32_t width = 0; 200 int32_t height = 0; 201 videoPlayer_->adapter->GetVideoWidth(width); 202 printf("[%s,%d] width:%d\n", __func__, __LINE__, width); 203 videoPlayer_->adapter->GetVideoHeight(height); 204 printf("[%s,%d] height:%d\n", __func__, __LINE__, height); 205 206 if (width <= 0 || height <= 0) { 207 videoPlayer_->adapter->Release(); 208 delete videoPlayer_; 209 videoPlayer_ = nullptr; 210 printf("******** width <= 0 || height <= 0 | return \n"); 211 ShowErrorTips(); 212 return false; 213 } 214 float ratio_x = static_cast<float>(width) / ROOT_VIEW_WIDTH; 215 float ratio_y = static_cast<float>(height) / ROOT_VIEW_HEIGHT; 216 uint16_t surfaceViewWidth; 217 uint16_t surfaceViewHeight; 218 uint16_t surfaceViewPositionX = 0; 219 uint16_t surfaceViewPositionY = 0; 220 if (ratio_x > ratio_y) { 221 surfaceViewWidth = ROOT_VIEW_WIDTH; 222 surfaceViewHeight = height / ratio_x; 223 surfaceViewPositionY = (ROOT_VIEW_HEIGHT - surfaceViewHeight) / 2; // 2: half 224 } else { 225 surfaceViewWidth = width / ratio_y; 226 surfaceViewHeight = ROOT_VIEW_HEIGHT; 227 surfaceViewPositionX = (ROOT_VIEW_WIDTH - surfaceViewWidth) / 2; // 2: half 228 } 229 230 surfaceView_ = new UISurfaceView(); 231 surfaceView_->SetPosition(surfaceViewPositionX, surfaceViewPositionY); 232 surfaceView_->SetWidth(surfaceViewWidth - 1); 233 surfaceView_->SetHeight(surfaceViewHeight); 234 videoPlayer_->adapter->SetVideoSurface(surfaceView_->GetSurface()); 235 236 rootView_->Add(surfaceView_); 237 238 return true; 239} 240 241void PlayerAbilitySlice::SetUpProgress(int64_t duration) 242{ 243 slider_ = new UISlider(); 244 slider_->SetPosition(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, STATUS_BAR_GROUP_HEIGHT); 245 slider_->SetValidHeight(SLIDER_HEIGHT); 246 slider_->SetValidWidth(SLIDER_WIDTH - KNOB_WIDTH); 247 slider_->SetRange(SLIDER_WIDTH, 0); 248 slider_->SetValue(0); 249 slider_->SetKnobWidth(KNOB_WIDTH); 250 slider_->SetSliderRadius(SLIDER_HEIGHT, SLIDER_HEIGHT); 251 slider_->SetKnobRadius(KNOB_WIDTH / 2); // 2: half 252 slider_->SetKnobStyle(STYLE_BACKGROUND_COLOR, Color::White().full); 253 slider_->SetBackgroundStyle(STYLE_BACKGROUND_COLOR, 0x1A888888); 254 slider_->SetBackgroundStyle(STYLE_BACKGROUND_OPA, 90); // 90: opacity is 90 255 slider_->SetDirection(UISlider::Direction::DIR_LEFT_TO_RIGHT); 256 slider_->SetTouchable(false); 257 animatorGroup_->Add(slider_); 258 259 animator_ = new SliderAnimator(videoPlayer_, slider_, currentTimeLabel_, duration, surfaceView_); 260} 261 262void PlayerAbilitySlice::SetUpAnimatorGroup(const char* pathHeader) 263{ 264 int64_t duration = 0; 265 videoPlayer_->adapter->GetDuration(duration); 266 printf("[%s,%d] GetDuration:%lld\n", __func__, __LINE__, duration); 267 268 animatorGroup_ = new UIViewGroup(); 269 animatorGroup_->SetPosition(0, ROOT_VIEW_HEIGHT - STATUS_BAR_GROUP_HEIGHT, 270 ROOT_VIEW_WIDTH, STATUS_BAR_GROUP_HEIGHT); 271 animatorGroup_->SetStyle(STYLE_BACKGROUND_OPA, 0); 272 273 totalTimeLabel_ = new UILabel(); 274 totalTimeLabel_->SetPosition(TOTAL_TIME_LABEL_X, TOTAL_TIME_LABEL_Y, 275 TOTAL_TIME_LABEL_WIDTH, TOTAL_TIME_LABEL_HEIGHT); 276 totalTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, 277 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); 278 totalTimeLabel_->SetFont(FONT_NAME, PLAYER_FONT_SIZE); 279 int64_t second = duration / 1000; // 1000: 1s = 1000ms 280 char timer[6]; // 6: length of time label 281 if (sprintf_s(timer, sizeof(timer), "%02lld:%02lld", second / 60, second % 60) < 0) { // 60: 1minute = 60s 282 return; 283 } 284 285 totalTimeLabel_->SetText(timer); 286 totalTimeLabel_->SetTextColor(Color::White()); 287 animatorGroup_->Add(totalTimeLabel_); 288 289 currentTimeLabel_ = new UILabel(); 290 currentTimeLabel_->SetPosition(CURRENT_TIME_LABEL_X, CURRENT_TIME_LABEL_Y, 291 CURRENT_TIME_LABEL_WIDTH, CURRENT_TIME_LABEL_HEIGHT); 292 currentTimeLabel_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); 293 currentTimeLabel_->SetFont(FONT_NAME, PLAYER_FONT_SIZE); 294 currentTimeLabel_->SetText("00:00"); 295 currentTimeLabel_->SetTextColor(Color::White()); 296 currentTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, 297 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); 298 animatorGroup_->Add(currentTimeLabel_); 299 300 SetUpProgress(duration); 301 302 SetUpToggleButton(pathHeader); 303 304 rootView_->Add(animatorGroup_); 305} 306 307void PlayerAbilitySlice::SetUpToggleButton(const char* pathHeader) 308{ 309 toggleButton_ = new UIToggleButton(); 310 toggleButton_->SetTouchable(false); 311 toggleButton_->SetPosition(TOGGLE_BUTTON_OFFSET_X, TOGGLE_BUTTON_OFFSET_Y, 312 TOGGLE_BUTTON_WIDTH, TOGGLE_BUTTON_HEIGHT); 313 toggleButton_->SetState(true); 314 315 if (sprintf_s(videoPlayAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PALY_PATH) < 0) { 316 printf("PlayerAbilitySlice::OnStart | videoPlayAbsolutePath\n"); 317 return; 318 } 319 320 if (sprintf_s(videoPauseAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PAUSE_PATH) < 0) { 321 printf("PlayerAbilitySlice::OnStart | videoPauseAbsolutePath\n"); 322 return; 323 } 324 toggleButton_->SetImages(videoPauseAbsolutePath, videoPlayAbsolutePath); 325 onClickListener_ = new ToggleBtnListener(toggleButton_, videoPlayer_, animator_, surfaceView_); 326 327 toggleButtonArea_ = new UIViewGroup(); 328 toggleButtonArea_->SetPosition(0, 0, TOGGLE_BUTTON_OFFSET_X + TOGGLE_BUTTON_WIDTH, STATUS_BAR_GROUP_HEIGHT); 329 toggleButtonArea_->SetTouchable(true); 330 toggleButtonArea_->SetOnClickListener(onClickListener_); 331 toggleButtonArea_->Add(toggleButton_); 332 333 animatorGroup_->Add(toggleButtonArea_); 334} 335 336void PlayerAbilitySlice::OnStart(const Want &want) 337{ 338 printf("@@@@@ PlayerAbilitySlice::OnStart\n"); 339 AbilitySlice::OnStart(want); 340 341 SetUpRootView(); 342 const char* pathHeader = GetSrcPath(); 343 SetUpVideoPlayer(want); 344 345 videoPlayer_->adapter->Prepare(); 346 347 if (!SetUpSurfaceView()) { 348 return; 349 } 350 SetUpBackArea(pathHeader); 351 SetUpAnimatorGroup(pathHeader); 352 353 SetUIContent(rootView_); 354 355 videoPlayer_->adapter->Play(); 356 animator_->SetToggleButton(toggleButton_); 357 animator_->SetToggleBtnListener(onClickListener_); 358 animator_->Start(); 359 360 printf("## @@@@@ PlayerAbilitySlice::OnStart | end \n"); 361} 362 363void PlayerAbilitySlice::OnInactive() 364{ 365 printf("PlayerAbilitySlice::OnInactive\n"); 366 AbilitySlice::OnInactive(); 367} 368 369void PlayerAbilitySlice::OnActive(const Want &want) 370{ 371 printf("PlayerAbilitySlice::OnActive\n"); 372 AbilitySlice::OnActive(want); 373} 374 375void PlayerAbilitySlice::OnBackground() 376{ 377 printf("PlayerAbilitySlice::OnBackground\n"); 378 AbilitySlice::OnBackground(); 379} 380 381void PlayerAbilitySlice::OnStop() 382{ 383 if (animator_ != nullptr) { 384 animator_->Stop(); 385 delete animator_; 386 animator_ = nullptr; 387 } 388 389 if (videoPlayer_ != nullptr && videoPlayer_->adapter.get() != nullptr) { 390 videoPlayer_->adapter->Stop(); 391 videoPlayer_->adapter->Reset(); 392 delete videoPlayer_; 393 videoPlayer_ = nullptr; 394 } 395 Clear(); 396 printf("PlayerAbilitySlice::OnStop\n"); 397 AbilitySlice::OnStop(); 398} 399 400void SliderAnimator::Callback(UIView* view) 401{ 402 if (needRefreshPlayer_) { 403 videoPlayer_->adapter->Stop(); 404 videoPlayer_->adapter->Reset(); 405 406 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer(); 407 std::string uri(videoPlayer_->filePath); 408 std::map<std::string, std::string> header; 409 Source source(uri, header); 410 videoPlayer_->adapter->SetSource(source); 411 videoPlayer_->adapter->Prepare(); 412 videoPlayer_->adapter->SetVideoSurface(surfaceView_->GetSurface()); 413 videoPlayer_->adapter->Play(); 414 needRefreshPlayer_ = false; 415 } 416 417 int64_t currentTime = 0; 418 videoPlayer_->adapter->GetCurrentTime(currentTime); 419 int64_t currentSecond = currentTime / 1000; // 1000: 1s = 1000ms 420 421 char time[6]; // 6: length of time label 422 sprintf_s(time, sizeof(time), "%02lld:%02lld", currentSecond / 60, currentSecond % 60); // 60: 1minute = 60s 423 timeLabel_->SetText(time); 424 timeLabel_->Invalidate(); 425 426 int64_t curPosition = currentTime * slider_->GetRangeMax() / duration_; 427 slider_->SetValue(curPosition); 428 slider_->Invalidate(); 429 430 if (currentTime >= duration_) { 431 listener_->SetCompleteFlag(true); 432 toggleButton_->SetState(false); 433 needRefreshPlayer_ = true; 434 Stop(); 435 } 436} 437 438bool ToggleBtnListener::OnClick(UIView &view, const ClickEvent& event) 439{ 440 button_->OnClickEvent(event); 441 if (completeFlag_) { 442 animator_->Start(); 443 button_->Invalidate(); 444 completeFlag_ = false; 445 return true; 446 } 447 448 if (button_->GetState()) { 449 videoPlayer_->adapter->Play(); 450 animator_->Resume(); 451 printf("ToggleBtnListener::OnClick | play\n"); 452 } else { 453 videoPlayer_->adapter->Pause(); 454 animator_->Pause(); 455 printf("ToggleBtnListener::OnClick | pause\n"); 456 } 457 button_->Invalidate(); 458 return true; 459} 460} 461