1 /* 2 * Copyright (c) 2021 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_ANIMATED_IMAGE_PLAYER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_ANIMATED_IMAGE_PLAYER_H 18 19 #include <unordered_map> 20 21 #include "include/codec/SkCodec.h" 22 23 #include "base/memory/ace_type.h" 24 #include "core/animation/animator.h" 25 #include "core/animation/picture_animation.h" 26 #include "core/image/image_provider.h" 27 #include "core/image/image_source_info.h" 28 #include "core/pipeline/pipeline_base.h" 29 30 namespace OHOS::Ace { 31 32 class AnimatedImagePlayer : public virtual AceType { 33 DECLARE_ACE_TYPE(AnimatedImagePlayer, AceType); 34 35 public: 36 AnimatedImagePlayer(ImageSourceInfo source, UploadSuccessCallback successCallback, 37 const WeakPtr<PipelineBase>& weakContext, std::unique_ptr<SkCodec> codec, int32_t dstWidth = -1, 38 int32_t dstHeight = -1) 39 : imageSource_(source), successCallback_(successCallback), context_(weakContext), codec_(std::move(codec)), 40 frameCount_(codec_->getFrameCount()), repetitionCount_(codec_->getRepetitionCount()), 41 frameInfos_(codec_->getFrameInfo()), dstWidth_(dstWidth), dstHeight_(dstHeight) 42 { 43 auto context = context_.Upgrade(); 44 if (context) { 45 animator_ = CREATE_ANIMATOR(context); 46 auto pictureAnimation = AceType::MakeRefPtr<PictureAnimation<int32_t>>(); 47 float totalFrameDuration = 0.0f; 48 int32_t lastRequiredIndex = -1; 49 for (int32_t index = 0; index < frameCount_; index++) { 50 // if frame duration is 0, set this frame duration as 100ms 51 if (frameInfos_[index].fDuration <= 0) { 52 frameInfos_[index].fDuration = 100; 53 } 54 totalFrameDuration += frameInfos_[index].fDuration; 55 56 // process required frame index. 57 int32_t requiredIndex = frameInfos_[index].fRequiredFrame; 58 // if requiredIndex is valid 59 if (requiredIndex >= 0 && requiredIndex < frameCount_) { 60 // if require prior frame before last frame, cache it after first loop. 61 if (requiredIndex < lastRequiredIndex) { 62 cachedFrame_.emplace(requiredIndex, nullptr); 63 } 64 lastRequiredIndex = requiredIndex; 65 } 66 } 67 for (int32_t index = 0; index < frameCount_; index++) { 68 pictureAnimation->AddPicture( 69 static_cast<float>(frameInfos_[index].fDuration) / totalFrameDuration, index); 70 } 71 pictureAnimation->AddListener([weak = WeakClaim(this)](const int32_t& index) { 72 auto player = weak.Upgrade(); 73 if (player) { 74 player->RenderFrame(index); 75 } 76 }); 77 animator_->AddInterpolator(pictureAnimation); 78 animator_->SetDuration(totalFrameDuration); 79 auto repetitionCount = context->IsJsCard() ? 1 : repetitionCount_; 80 animator_->SetIteration(repetitionCount > 0 ? repetitionCount : ANIMATION_REPEAT_INFINITE); 81 animator_->Play(); 82 } 83 } 84 85 ~AnimatedImagePlayer() override = default; 86 87 void Pause(); 88 void Resume(); 89 void RenderFrame(const int32_t& index); 90 SetTargetSize(int32_t width,int32_t height)91 void SetTargetSize(int32_t width, int32_t height) 92 { 93 dstWidth_ = width; 94 dstHeight_ = height; 95 } 96 97 private: 98 #ifndef USE_ROSEN_DRAWING 99 sk_sp<SkImage> DecodeFrameImage(const int32_t& index); 100 static bool CopyTo(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src); 101 #else 102 std::shared_ptr<RSImage> DecodeFrameImage(const int32_t& index); 103 static bool CopyTo(RSBitmap* dst, const RSBitmap& src); 104 #endif 105 106 ImageSourceInfo imageSource_; 107 UploadSuccessCallback successCallback_; 108 WeakPtr<PipelineBase> context_; 109 110 const std::unique_ptr<SkCodec> codec_; 111 const int32_t frameCount_; 112 const int32_t repetitionCount_; 113 std::vector<SkCodec::FrameInfo> frameInfos_; 114 115 RefPtr<Animator> animator_; 116 int32_t dstWidth_ = -1; 117 int32_t dstHeight_ = -1; 118 119 #ifndef USE_ROSEN_DRAWING 120 // used to cache required frame. 121 std::unordered_map<int32_t, std::unique_ptr<SkBitmap>> cachedFrame_; 122 123 // used to cache last required frame. this will be reset during looping. 124 std::unique_ptr<SkBitmap> lastRequiredBitmap_; 125 #else 126 // used to cache required frame. 127 std::unordered_map<int32_t, std::unique_ptr<RSBitmap>> cachedFrame_; 128 129 // used to cache last required frame. this will be reset during looping. 130 std::unique_ptr<RSBitmap> lastRequiredBitmap_; 131 #endif 132 int32_t lastRequiredFrameIndex_ = -1; 133 }; 134 135 } // namespace OHOS::Ace 136 137 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_ANIMATED_IMAGE_PLAYER_H 138