• 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 #include "core/components_ng/render/drawing.h"
19 #include "drawing/engine_adapter/skia_adapter/skia_image_info.h"
20 #ifdef USE_NEW_SKIA
21 #include "include/codec/SkCodecAnimation.h"
22 #endif
23 
24 namespace OHOS::Ace {
25 
Pause()26 void AnimatedImagePlayer::Pause()
27 {
28     animator_->Pause();
29 }
30 
Resume()31 void AnimatedImagePlayer::Resume()
32 {
33     animator_->Resume();
34 }
35 
RenderFrame(const int32_t & index)36 void AnimatedImagePlayer::RenderFrame(const int32_t& index)
37 {
38     auto context = context_.Upgrade();
39     if (!context) {
40         LOGW("Context may be destroyed!");
41         return;
42     }
43     auto taskExecutor = context->GetTaskExecutor();
44     taskExecutor->PostTask(
45         [weak = AceType::WeakClaim(this), index, dstWidth = dstWidth_, dstHeight = dstHeight_, taskExecutor] {
46             ACE_SCOPED_TRACE("decode frame %d", index);
47             auto player = weak.Upgrade();
48             if (!player) {
49                 return;
50             }
51             std::shared_ptr<RSImage> dImage = player->DecodeFrameImage(index);
52             if (dstWidth > 0 && dstHeight > 0) {
53                 dImage = ImageProvider::ApplySizeToDrawingImage(dImage, dstWidth, dstHeight);
54             }
55             if (!dImage) {
56                 LOGW("animated player cannot get the %{public}d dImage!", index);
57                 return;
58             }
59             auto canvasImage = NG::CanvasImage::Create(&dImage);
60 #ifdef PREVIEW
61             player->successCallback_(player->imageSource_, canvasImage);
62         },
63         TaskExecutor::TaskType::UI, "ArkUIImagePlayerRenderAnimatedFrame");
64 #else
65             taskExecutor->PostTask([callback = player->successCallback_, canvasImage,
66                                        source = player->imageSource_] { callback(source, canvasImage); },
67                 TaskExecutor::TaskType::UI, "ArkUIImageRenderAnimatedFrameSuccess");
68         },
69         TaskExecutor::TaskType::IO, "ArkUIImagePlayerRenderAnimatedFrame");
70 #endif
71 }
72 
DecodeFrameImage(const int32_t & index)73 std::shared_ptr<RSImage> AnimatedImagePlayer::DecodeFrameImage(const int32_t& index)
74 {
75     // first seek in cache
76     auto iterator = cachedFrame_.find(index);
77     if (iterator != cachedFrame_.end() && iterator->second != nullptr) {
78         auto image = std::shared_ptr<RSImage>();
79         if (!image) {
80             return nullptr;
81         }
82         image->BuildFromBitmap(*iterator->second);
83         return image;
84     }
85 
86     RSBitmap bitmap;
87     SkImageInfo skImageInfo = codec_->getInfo().makeColorType(kN32_SkColorType);
88     auto imageInfo = Rosen::Drawing::SkiaImageInfo::ConvertToRSImageInfo(skImageInfo);
89     bitmap.Build(imageInfo);
90     SkCodec::Options options;
91     options.fFrameIndex = index;
92     const int32_t requiredFrame = frameInfos_[index].fRequiredFrame;
93     if (requiredFrame != SkCodec::kNoFrame) {
94         if (requiredFrame == lastRequiredFrameIndex_ && lastRequiredBitmap_ && lastRequiredBitmap_->GetPixels() &&
95             CopyTo(&bitmap, *lastRequiredBitmap_)) {
96             options.fPriorFrame = requiredFrame;
97         } else if (requiredFrame != lastRequiredFrameIndex_) {
98             // find requiredFrame in cached frame.
99             auto iter = cachedFrame_.find(requiredFrame);
100             if (iter != cachedFrame_.end() && iter->second != nullptr &&
101                 CopyTo(&bitmap, *iter->second)) {
102                 options.fPriorFrame = requiredFrame;
103             }
104         }
105     }
106 
107     if (SkCodec::kSuccess != codec_->getPixels(skImageInfo, bitmap.GetPixels(), bitmap.GetRowBytes(), &options)) {
108         LOGW("Could not getPixels for frame %{public}d:", index);
109         return nullptr;
110     }
111 
112     if (frameInfos_[index].fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
113         lastRequiredBitmap_ = std::make_unique<RSBitmap>(bitmap);
114         lastRequiredFrameIndex_ = index;
115     }
116 
117     if (iterator != cachedFrame_.end() && iterator->second == nullptr) {
118         iterator->second = std::make_unique<RSBitmap>(bitmap);
119     }
120     auto image = std::make_shared<RSImage>();
121     if (!image) {
122         return nullptr;
123     }
124     image->BuildFromBitmap(bitmap);
125     return image;
126 }
127 
CopyTo(RSBitmap * dst,const RSBitmap & src)128 bool AnimatedImagePlayer::CopyTo(RSBitmap* dst, const RSBitmap& src)
129 {
130     auto info = src.GetImageInfo();
131     dst->Build(info);
132     src.CopyPixels(*dst, 0, 0);
133     return true;
134 }
135 } // namespace OHOS::Ace
136