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