• 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 #include "core/image/animated_image_player.h"
17 
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/codec/SkCodecAnimation.h"
20 #include "include/core/SkPixelRef.h"
21 #endif
22 
23 #include "base/log/ace_trace.h"
24 #include "base/log/log.h"
25 #include "base/memory/ace_type.h"
26 #include "core/components_ng/render/canvas_image.h"
27 #ifdef USE_ROSEN_DRAWING
28 #include "core/components_ng/render/drawing.h"
29 #endif
30 #include "core/image/image_provider.h"
31 
32 namespace OHOS::Ace {
33 
Pause()34 void AnimatedImagePlayer::Pause()
35 {
36     animator_->Pause();
37 }
38 
Resume()39 void AnimatedImagePlayer::Resume()
40 {
41     animator_->Resume();
42 }
43 
RenderFrame(const int32_t & index)44 void AnimatedImagePlayer::RenderFrame(const int32_t& index)
45 {
46     auto context = context_.Upgrade();
47     if (!context) {
48         LOGW("Context may be destroyed!");
49         return;
50     }
51     auto taskExecutor = context->GetTaskExecutor();
52     taskExecutor->PostTask(
53         [weak = AceType::WeakClaim(this), index, dstWidth = dstWidth_, dstHeight = dstHeight_, taskExecutor] {
54             ACE_SCOPED_TRACE("decode frame %d", index);
55             auto player = weak.Upgrade();
56             if (!player) {
57                 return;
58             }
59 
60 #ifndef USE_ROSEN_DRAWING
61             sk_sp<SkImage> skImage = player->DecodeFrameImage(index);
62             if (dstWidth > 0 && dstHeight > 0) {
63                 skImage = ImageProvider::ApplySizeToSkImage(skImage, dstWidth, dstHeight);
64             }
65             if (!skImage) {
66                 LOGW("animated player cannot get the %{public}d skImage!", index);
67                 return;
68             }
69             auto canvasImage = NG::CanvasImage::Create(&skImage);
70 #else
71             std::shared_ptr<RSImage> dImage = player->DecodeFrameImage(index);
72             if (dstWidth > 0 && dstHeight > 0) {
73                 dImage = ImageProvider::ApplySizeToDrawingImage(dImage, dstWidth, dstHeight);
74             }
75             if (!dImage) {
76                 LOGW("animated player cannot get the %{public}d dImage!", index);
77                 return;
78             }
79             auto canvasImage = NG::CanvasImage::Create(&dImage);
80 #endif
81 #ifdef PREVIEW
82             player->successCallback_(player->imageSource_, canvasImage);
83         },
84         TaskExecutor::TaskType::UI);
85 #else
86             taskExecutor->PostTask([callback = player->successCallback_, canvasImage,
87                                        source = player->imageSource_] { callback(source, canvasImage); },
88                 TaskExecutor::TaskType::UI);
89         },
90         TaskExecutor::TaskType::IO);
91 #endif
92 }
93 
94 #ifndef USE_ROSEN_DRAWING
DecodeFrameImage(const int32_t & index)95 sk_sp<SkImage> AnimatedImagePlayer::DecodeFrameImage(const int32_t& index)
96 {
97     // first seek in cache
98     auto iterator = cachedFrame_.find(index);
99     if (iterator != cachedFrame_.end() && iterator->second != nullptr) {
100         LOGD("index %{private}d found in cache.", index);
101         return SkImage::MakeFromBitmap(*iterator->second);
102     }
103 
104     SkBitmap bitmap;
105     SkImageInfo info = codec_->getInfo().makeColorType(kN32_SkColorType);
106     bitmap.allocPixels(info);
107     SkCodec::Options options;
108     options.fFrameIndex = index;
109     const int32_t requiredFrame = frameInfos_[index].fRequiredFrame;
110     if (requiredFrame != SkCodec::kNoFrame) {
111         if (requiredFrame == lastRequiredFrameIndex_ && lastRequiredBitmap_ && lastRequiredBitmap_->getPixels() &&
112             CopyTo(&bitmap, lastRequiredBitmap_->colorType(), *lastRequiredBitmap_)) {
113             options.fPriorFrame = requiredFrame;
114         } else if (requiredFrame != lastRequiredFrameIndex_) {
115             // find requiredFrame in cached frame.
116             auto iter = cachedFrame_.find(requiredFrame);
117             if (iter != cachedFrame_.end() && iter->second != nullptr &&
118                 CopyTo(&bitmap, iter->second->colorType(), *iter->second)) {
119                 options.fPriorFrame = requiredFrame;
120             }
121         }
122     }
123 
124     if (SkCodec::kSuccess != codec_->getPixels(info, bitmap.getPixels(), bitmap.rowBytes(), &options)) {
125         LOGW("Could not getPixels for frame %{public}d:", index);
126         return nullptr;
127     }
128 
129     if (frameInfos_[index].fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
130         lastRequiredBitmap_ = std::make_unique<SkBitmap>(bitmap);
131         lastRequiredFrameIndex_ = index;
132     }
133 
134     if (iterator != cachedFrame_.end() && iterator->second == nullptr) {
135         LOGD("index %{private}d cached.", index);
136         iterator->second = std::make_unique<SkBitmap>(bitmap);
137     }
138     return SkImage::MakeFromBitmap(bitmap);
139 }
140 #else
DecodeFrameImage(const int32_t & index)141 std::shared_ptr<RSImage> AnimatedImagePlayer::DecodeFrameImage(const int32_t& index)
142 {
143     LOGE("Drawing is not supported");
144     return std::make_shared<RSImage>();
145 }
146 #endif
147 
CopyTo(SkBitmap * dst,SkColorType dstColorType,const SkBitmap & src)148 bool AnimatedImagePlayer::CopyTo(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src)
149 {
150     SkPixmap srcPixmap;
151     if (!src.peekPixels(&srcPixmap)) {
152         return false;
153     }
154     SkBitmap tempDstBitmap;
155     SkImageInfo dstInfo = srcPixmap.info().makeColorType(dstColorType);
156     if (!tempDstBitmap.setInfo(dstInfo)) {
157         return false;
158     }
159     if (!tempDstBitmap.tryAllocPixels()) {
160         return false;
161     }
162     SkPixmap dstPixmap;
163     if (!tempDstBitmap.peekPixels(&dstPixmap)) {
164         return false;
165     }
166     if (!srcPixmap.readPixels(dstPixmap)) {
167         return false;
168     }
169     dst->swap(tempDstBitmap);
170     return true;
171 }
172 
173 } // namespace OHOS::Ace
174