1 /*
2  * Copyright (c) 2023 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 "ohos_image_decoder_adapter_impl.h"
17 
18 #include "foundation/graphic/graphic_surface/interfaces/inner_api/surface/window.h"
19 #include "fstream"
20 #include "image_source.h"
21 #include "istream"
22 #include "media_errors.h"
23 #include "nweb_log.h"
24 #include "pixel_map.h"
25 #include "sstream"
26 #include "string"
27 
28 namespace OHOS {
29 namespace NWeb {
30 
31 namespace {
32 
ParseRawData(const uint8_t * data,uint32_t size,Media::ImageInfo & imageInfo)33 std::unique_ptr<Media::ImageSource> ParseRawData(const uint8_t* data,
34                                                  uint32_t size,
35                                                  Media::ImageInfo& imageInfo)
36 {
37     uint32_t errorCode = 0;
38     Media::SourceOptions sourceOptions;
39     auto imageSource = Media::ImageSource::CreateImageSource(
40         data, size, sourceOptions, errorCode);
41     if (errorCode != Media::SUCCESS) {
42         WVLOG_E("[HeifSupport] ParseRawData failed, errorCode %{public}d", errorCode);
43         return nullptr;
44     }
45 
46     auto ret = imageSource->GetImageInfo(imageInfo);
47     if (ret != Media::SUCCESS) {
48         WVLOG_E(
49             "[HeifSupport] ParseRawData GetImageInfo failed, errorCode %{public}d", ret);
50         return nullptr;
51     }
52     return imageSource;
53 }
54 
SurfaceBufferFromPixelMap(Media::PixelMap * pixelMap)55 SurfaceBuffer* SurfaceBufferFromPixelMap(Media::PixelMap* pixelMap)
56 {
57     if (pixelMap && pixelMap->GetFd()) {
58         return reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd());
59     }
60     return nullptr;
61 }
62 
63 };  // namespace
64 
65 OhosImageDecoderAdapterImpl::OhosImageDecoderAdapterImpl() = default;
66 
~OhosImageDecoderAdapterImpl()67 OhosImageDecoderAdapterImpl::~OhosImageDecoderAdapterImpl()
68 {
69     ReleasePixelMap();
70 }
71 
ParseImageInfo(const uint8_t * data,uint32_t size)72 bool OhosImageDecoderAdapterImpl::ParseImageInfo(const uint8_t* data, uint32_t size)
73 {
74     return ParseRawData(data, size, imageInfo_) != nullptr;
75 }
76 
GetEncodedFormat()77 std::string OhosImageDecoderAdapterImpl::GetEncodedFormat()
78 {
79     return imageInfo_.encodedFormat;
80 }
81 
GetImageWidth()82 int32_t OhosImageDecoderAdapterImpl::GetImageWidth()
83 {
84     return imageInfo_.size.width;
85 }
86 
GetImageHeight()87 int32_t OhosImageDecoderAdapterImpl::GetImageHeight()
88 {
89     return imageInfo_.size.height;
90 }
91 
DecodeToPixelMap(const uint8_t * data,uint32_t size)92 bool OhosImageDecoderAdapterImpl::DecodeToPixelMap(const uint8_t* data, uint32_t size)
93 {
94     return Decode(data, size, AllocatorType::kDmaAlloc, false);
95 }
96 
Decode(const uint8_t * data,uint32_t size,AllocatorType type,bool useYuv)97 bool OhosImageDecoderAdapterImpl::Decode(const uint8_t* data,
98                                          uint32_t size,
99                                          AllocatorType type,
100                                          bool useYuv)
101 {
102     // Manage lifecycle of pixelmap and native window buffer with map next.
103     WVLOG_I("[HeifSupport] OhosImageDecoderAdapterImpl DecodeToPixelMap.");
104     auto imageSource = ParseRawData(data, size, imageInfo_);
105     if (imageSource == nullptr) {
106         WVLOG_E(
107             "[HeifSupport] OhosImageDecoderAdapterImpl::DecodeToPixelMap, fail to get image source.");
108         return false;
109     }
110 
111     uint32_t errorCode = 0;
112     Media::DecodeOptions decodeOptions;
113     decodeOptions.desiredPixelFormat =
114         useYuv ? Media::PixelFormat::NV12 : Media::PixelFormat::RGBA_8888;
115     decodeOptions.allocatorType = static_cast<Media::AllocatorType>(type);
116     pixelMap_ = imageSource->CreatePixelMap(decodeOptions, errorCode);
117     if (errorCode != Media::SUCCESS) {
118         WVLOG_E("[HeifSupport] CreatePixelMap failed, errorCode %{public}d", errorCode);
119         return false;
120     }
121 
122     return true;
123 }
124 
GetFd()125 int32_t OhosImageDecoderAdapterImpl::GetFd()
126 {
127     if (!pixelMap_) {
128         WVLOG_E("[HeifSupport] OhosImageDecoderAdapterImpl::GetFd. PixelMap is null.");
129         return -1;
130     }
131     if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
132         return surfaceBuffer->GetFileDescriptor();
133     }
134     WVLOG_E(
135         "[HeifSupport] OhosImageDecoderAdapterImpl::GetFd. Fail to get surface buffer.");
136 
137     return -1;
138 }
139 
GetStride()140 int32_t OhosImageDecoderAdapterImpl::GetStride()
141 {
142     if (!pixelMap_) {
143         WVLOG_E(
144             "[HeifSupport] OhosImageDecoderAdapterImpl::GetStride. PixelMap is null.");
145         return 0;
146     }
147     if (pixelMap_->GetAllocatorType() == Media::AllocatorType::SHARE_MEM_ALLOC) {
148         WVLOG_D("[HeifSupport] OhosImageDecoderAdapterImpl::GetStride. share mem get row stride.");
149         return pixelMap_->GetRowStride();
150     }
151     if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
152         // Pixmap row stride is suface buffer stride as We only support DMA_ALLOC now.
153         return surfaceBuffer->GetStride();
154     }
155     WVLOG_E(
156         "[HeifSupport] OhosImageDecoderAdapterImpl::GetStride. Fail to get surface buffer.");
157 
158     return 0;
159 }
160 
GetOffset()161 int32_t OhosImageDecoderAdapterImpl::GetOffset()
162 {
163     if (!pixelMap_) {
164         WVLOG_E(
165             "[HeifSupport] OhosImageDecoderAdapterImpl::GetOffset. PixelMap is null.");
166         return 0;
167     }
168     if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
169         OH_NativeBuffer_Planes* native_buffer_planes_;
170         surfaceBuffer->GetPlanesInfo((void**)&native_buffer_planes_);
171         if (!native_buffer_planes_) {
172             WVLOG_E(
173                 "[HeifSupport] OhosImageDecoderAdapterImpl::GetOffset. Fail to get native buffer Planes.");
174             return 0;
175         }
176         return native_buffer_planes_->planes[0].offset;
177     }
178     WVLOG_E(
179         "[HeifSupport] OhosImageDecoderAdapterImpl::GetStride. Fail to get surface buffer.");
180 
181     return 0;
182 }
183 
GetSize()184 uint64_t OhosImageDecoderAdapterImpl::GetSize()
185 {
186     if (!pixelMap_) {
187         WVLOG_E(
188             "[HeifSupport] OhosImageDecoderAdapterImpl::GetSize. PixelMap is null.");
189         return 0;
190     }
191     if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
192         return surfaceBuffer->GetSize();
193     }
194     WVLOG_E(
195         "[HeifSupport] OhosImageDecoderAdapterImpl::GetSize. Fail to get surface buffer.");
196 
197     return 0;
198 }
199 
GetNativeWindowBuffer()200 void* OhosImageDecoderAdapterImpl::GetNativeWindowBuffer()
201 {
202     if (!pixelMap_) {
203         WVLOG_E(
204             "[HeifSupport] OhosImageDecoderAdapterImpl::GetNativeWindowBuffer. PixelMap is null.");
205         return nullptr;
206     }
207     if (!nativeWindowBuffer_) {
208         if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
209             nativeWindowBuffer_ =
210                 CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
211         }
212     }
213     return static_cast<void*>(nativeWindowBuffer_);
214 }
215 
216 // Used for NV12
GetPlanesCount()217 int32_t OhosImageDecoderAdapterImpl::GetPlanesCount()
218 {
219     if (!pixelMap_) {
220         WVLOG_E(
221             "[HeifSupport] OhosImageDecoderAdapterImpl::GetPlanesCount. PixelMap is null.");
222         return 0;
223     }
224 
225     if (auto* surfaceBuffer = SurfaceBufferFromPixelMap(pixelMap_.get())) {
226         OH_NativeBuffer_Planes* nativeBufferPlanes;
227         surfaceBuffer->GetPlanesInfo((void**)&nativeBufferPlanes);
228         if (!nativeBufferPlanes) {
229             WVLOG_E(
230                 "[HeifSupport] OhosImageDecoderAdapterImpl::GetPlanesCount. Fail to get native buffer Planes.");
231             return 0;
232         }
233         return nativeBufferPlanes->planeCount;
234     }
235     WVLOG_E(
236         "[HeifSupport] OhosImageDecoderAdapterImpl::GetPlanesCount. Fail to get surface buffer.");
237 
238     return 0;
239 }
240 
ReleasePixelMap()241 void OhosImageDecoderAdapterImpl::ReleasePixelMap()
242 {
243     WVLOG_I("[HeifSupport] OhosImageDecoderAdapterImpl release pixelmap and native window buffer.");
244     if (pixelMap_) {
245         pixelMap_.reset();
246         pixelMap_ = nullptr;
247     }
248     if (nativeWindowBuffer_) {
249         DestroyNativeWindowBuffer(nativeWindowBuffer_);
250         nativeWindowBuffer_ = nullptr;
251     }
252 }
253 
GetDecodeData()254 void* OhosImageDecoderAdapterImpl::GetDecodeData()
255 {
256     if (!pixelMap_) {
257         WVLOG_E("[HeifSupport] OhosImageDecoderAdapterImpl::GetDecodeData. PixelMap is null.");
258         return nullptr;
259     }
260     return pixelMap_->GetWritablePixels();
261 }
262 
263 }  // namespace NWeb
264 }  // namespace OHOS