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