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 "bmp_decoder.h"
17
18 #include "image_log.h"
19 #include "image_trace.h"
20 #include "image_utils.h"
21 #include "media_errors.h"
22 #include "securec.h"
23 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
24 #include "surface_buffer.h"
25 #endif
26
27 #undef LOG_DOMAIN
28 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
29
30 #undef LOG_TAG
31 #define LOG_TAG "BmpDecoder"
32
33 namespace OHOS {
34 namespace ImagePlugin {
35 using namespace Media;
36 using namespace std;
37 namespace {
38 constexpr uint32_t BMP_IMAGE_NUM = 1;
39 }
40
SetSource(InputDataStream & sourceStream)41 void BmpDecoder::SetSource(InputDataStream &sourceStream)
42 {
43 stream_ = &sourceStream;
44 state_ = BmpDecodingState::SOURCE_INITED;
45 }
46
Reset()47 void BmpDecoder::Reset()
48 {
49 if (stream_ != nullptr) {
50 stream_->Seek(0);
51 }
52 codec_.release();
53 info_.reset();
54 desireColor_ = kUnknown_SkColorType;
55 }
56
GetImageSize(uint32_t index,Size & size)57 uint32_t BmpDecoder::GetImageSize(uint32_t index, Size &size)
58 {
59 if (index >= BMP_IMAGE_NUM) {
60 IMAGE_LOGE("GetImageSize failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM);
61 return ERR_IMAGE_INVALID_PARAMETER;
62 }
63 if (state_ < BmpDecodingState::SOURCE_INITED) {
64 IMAGE_LOGE("GetImageSize failed, invalid state:%{public}d", state_);
65 return ERR_MEDIA_INVALID_OPERATION;
66 }
67 if (state_ >= BmpDecodingState::BASE_INFO_PARSED) {
68 size.width = info_.width();
69 size.height = info_.height();
70 return SUCCESS;
71 }
72 if (!DecodeHeader()) {
73 IMAGE_LOGE("GetImageSize failed, decode header failed, state=%{public}d", state_);
74 return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
75 }
76 size.width = info_.width();
77 size.height = info_.height();
78 state_ = BmpDecodingState::BASE_INFO_PARSED;
79 return SUCCESS;
80 }
81
SetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)82 uint32_t BmpDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
83 {
84 if (index >= BMP_IMAGE_NUM) {
85 IMAGE_LOGE("SetDecodeOptions failed, invalid index:%{public}u, range:%{public}u", index,
86 BMP_IMAGE_NUM);
87 return ERR_IMAGE_INVALID_PARAMETER;
88 }
89 if (state_ < BmpDecodingState::SOURCE_INITED) {
90 IMAGE_LOGE("SetDecodeOptions failed, invalid state %{public}d", state_);
91 return ERR_MEDIA_INVALID_OPERATION;
92 }
93 if (state_ >= BmpDecodingState::IMAGE_DECODING) {
94 Reset();
95 state_ = BmpDecodingState::SOURCE_INITED;
96 }
97 if (state_ < BmpDecodingState::BASE_INFO_PARSED) {
98 if (!DecodeHeader()) {
99 IMAGE_LOGE("GetImageSize failed, decode header failed, state=%{public}d", state_);
100 return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
101 }
102 state_ = BmpDecodingState::BASE_INFO_PARSED;
103 }
104 PixelFormat desiredFormat = opts.desiredPixelFormat;
105 desireColor_ = ConvertToColorType(desiredFormat, info.pixelFormat);
106 info.size.width = info_.width();
107 info.size.height = info_.height();
108 info.alphaType = ConvertToAlphaType(info_.alphaType());
109 state_ = BmpDecodingState::IMAGE_DECODING;
110 return SUCCESS;
111 }
112
SetShareMemBuffer(uint64_t byteCount,DecodeContext & context)113 uint32_t BmpDecoder::SetShareMemBuffer(uint64_t byteCount, DecodeContext &context)
114 {
115 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
116 uint32_t id = context.pixelmapUniqueId_;
117 std::string name = "BMP RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(id);
118 int fd = AshmemCreate(name.c_str(), byteCount);
119 if (fd < 0) {
120 return ERR_SHAMEM_DATA_ABNORMAL;
121 }
122 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
123 if (result < 0) {
124 ::close(fd);
125 return ERR_SHAMEM_DATA_ABNORMAL;
126 }
127 void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
128 if (ptr == MAP_FAILED) {
129 ::close(fd);
130 return ERR_SHAMEM_DATA_ABNORMAL;
131 }
132 context.pixelsBuffer.buffer = ptr;
133 void *fdBuffer = new int32_t();
134 if (fdBuffer == nullptr) {
135 ::munmap(ptr, byteCount);
136 ::close(fd);
137 context.pixelsBuffer.buffer = nullptr;
138 return ERR_SHAMEM_DATA_ABNORMAL;
139 }
140 *static_cast<int32_t *>(fdBuffer) = fd;
141 context.pixelsBuffer.context = fdBuffer;
142 context.pixelsBuffer.bufferSize = byteCount;
143 context.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
144 context.freeFunc = nullptr;
145 #endif
146 return SUCCESS;
147 }
148
DmaMemAlloc(uint64_t count,DecodeContext & context,SkImageInfo & dstInfo)149 static uint32_t DmaMemAlloc(uint64_t count, DecodeContext &context, SkImageInfo &dstInfo)
150 {
151 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
152 IMAGE_LOGE("Unsupport dma mem alloc");
153 return ERR_IMAGE_DATA_UNSUPPORT;
154 #else
155 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
156 BufferRequestConfig requestConfig = {
157 .width = dstInfo.width(),
158 .height = dstInfo.height(),
159 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
160 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
161 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
162 .timeout = 0,
163 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
164 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
165 };
166 GSError ret = sb->Alloc(requestConfig);
167 if (ret != GSERROR_OK) {
168 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
169 return ERR_DMA_NOT_EXIST;
170 }
171 void* nativeBuffer = sb.GetRefPtr();
172 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
173 if (err != OHOS::GSERROR_OK) {
174 IMAGE_LOGE("NativeBufferReference failed");
175 return ERR_DMA_DATA_ABNORMAL;
176 }
177 context.pixelsBuffer.buffer = static_cast<uint8_t*>(sb->GetVirAddr());
178 context.pixelsBuffer.bufferSize = count;
179 context.pixelsBuffer.context = nativeBuffer;
180 context.allocatorType = AllocatorType::DMA_ALLOC;
181 context.freeFunc = nullptr;
182 return SUCCESS;
183 #endif
184 }
185
SetBuffer(uint64_t byteCount,DecodeContext & context)186 uint32_t SetBuffer(uint64_t byteCount, DecodeContext &context)
187 {
188 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
189 if (byteCount == 0) {
190 IMAGE_LOGE("Decode failed, byteCount is invalid value");
191 return ERR_MEDIA_INVALID_VALUE;
192 }
193 void *outputBuffer = malloc(byteCount);
194 if (outputBuffer == nullptr) {
195 IMAGE_LOGE("Decode failed, alloc output buffer size:[%{public}llu] error",
196 static_cast<unsigned long long>(byteCount));
197 return ERR_IMAGE_MALLOC_ABNORMAL;
198 }
199 #ifdef _WIN32
200 if (memset_s(outputBuffer, 0, byteCount) != EOK) {
201 IMAGE_LOGE("Decode failed, memset buffer failed", backRet);
202 free(outputBuffer);
203 outputBuffer = nullptr;
204 return ERR_IMAGE_DECODE_FAILED;
205 }
206 #else
207 if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) {
208 IMAGE_LOGE("Decode failed, memset buffer failed");
209 free(outputBuffer);
210 outputBuffer = nullptr;
211 return ERR_IMAGE_DECODE_FAILED;
212 }
213 #endif
214 context.pixelsBuffer.buffer = outputBuffer;
215 context.pixelsBuffer.bufferSize = byteCount;
216 context.pixelsBuffer.context = nullptr;
217 context.allocatorType = AllocatorType::HEAP_ALLOC;
218 context.freeFunc = nullptr;
219 context.freeFunc = nullptr;
220 #endif
221 return SUCCESS;
222 }
223
SetBufferForPlatform(uint64_t byteCount,DecodeContext & context)224 uint32_t SetBufferForPlatform(uint64_t byteCount, DecodeContext &context)
225 {
226 if (byteCount == 0) {
227 IMAGE_LOGE("Decode failed, byteCount is invalid value");
228 return ERR_MEDIA_INVALID_VALUE;
229 }
230 void *outputBuffer = malloc(byteCount);
231 if (outputBuffer == nullptr) {
232 IMAGE_LOGE("Decode failed, alloc output buffer size:[%{public}llu] error",
233 static_cast<unsigned long long>(byteCount));
234 return ERR_IMAGE_MALLOC_ABNORMAL;
235 }
236 #ifdef _WIN32
237 if (memset_s(outputBuffer, 0, byteCount) != EOK) {
238 IMAGE_LOGE("Decode failed, memset buffer failed", backRet);
239 free(outputBuffer);
240 outputBuffer = nullptr;
241 return ERR_IMAGE_DECODE_FAILED;
242 }
243 #else
244 if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) {
245 IMAGE_LOGE("Decode failed, memset buffer failed");
246 free(outputBuffer);
247 outputBuffer = nullptr;
248 return ERR_IMAGE_DECODE_FAILED;
249 }
250 #endif
251 context.pixelsBuffer.buffer = outputBuffer;
252 context.pixelsBuffer.bufferSize = byteCount;
253 context.pixelsBuffer.context = nullptr;
254 context.allocatorType = AllocatorType::HEAP_ALLOC;
255 context.freeFunc = nullptr;
256 return SUCCESS;
257 }
258
SetContextPixelsBuffer(uint64_t byteCount,DecodeContext & context,SkImageInfo & dstInfo)259 uint32_t BmpDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context, SkImageInfo &dstInfo)
260 {
261 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
262 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
263 uint32_t res = SetShareMemBuffer(byteCount, context);
264 if (res != SUCCESS) {
265 return res;
266 }
267 } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
268 uint32_t res = DmaMemAlloc(byteCount, context, dstInfo);
269 if (res != SUCCESS) {
270 return res;
271 }
272 } else {
273 uint32_t res = SetBuffer(byteCount, context);
274 if (res != SUCCESS) {
275 return res;
276 }
277 }
278 #else
279 uint32_t res = SetBufferForPlatform(byteCount, context);
280 if (res != SUCCESS) {
281 return res;
282 }
283 #endif
284 return SUCCESS;
285 }
286
Decode(uint32_t index,DecodeContext & context)287 uint32_t BmpDecoder::Decode(uint32_t index, DecodeContext &context)
288 {
289 ImageTrace imageTrace("BmpDecoder::Decode, index:%u", index);
290 if (index >= BMP_IMAGE_NUM) {
291 IMAGE_LOGE("Decode failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM);
292 return ERR_IMAGE_INVALID_PARAMETER;
293 }
294 if (codec_ == nullptr) {
295 IMAGE_LOGE("Decode failed, codec is null");
296 return ERR_IMAGE_DECODE_FAILED;
297 }
298 if (state_ != BmpDecodingState::IMAGE_DECODING) {
299 IMAGE_LOGE("Decode failed, invalid state %{public}d", state_);
300 return ERR_MEDIA_INVALID_OPERATION;
301 }
302
303 SkImageInfo dstInfo = info_.makeColorType(desireColor_);
304 if (ImageUtils::CheckMulOverflow(dstInfo.width(), dstInfo.height(), dstInfo.bytesPerPixel())) {
305 IMAGE_LOGE("Decode failed, width:%{public}d, height:%{public}d is too large",
306 dstInfo.width(), dstInfo.height());
307 return ERR_IMAGE_DECODE_FAILED;
308 }
309 if (context.pixelsBuffer.buffer == nullptr) {
310 uint64_t byteCount = static_cast<uint64_t>(dstInfo.height()) * dstInfo.width() * dstInfo.bytesPerPixel();
311 uint32_t res = SetContextPixelsBuffer(byteCount, context, dstInfo);
312 if (res != SUCCESS) {
313 return res;
314 }
315 }
316 uint8_t *dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
317 size_t rowBytes = dstInfo.width() * dstInfo.bytesPerPixel();
318 SkCodec::Result ret = codec_->getPixels(dstInfo, dstBuffer, rowBytes);
319 if (ret != SkCodec::kSuccess) {
320 IMAGE_LOGE("Decode failed, get pixels failed, ret=%{public}d", ret);
321 state_ = BmpDecodingState::IMAGE_ERROR;
322 return ERR_IMAGE_DECODE_ABNORMAL;
323 }
324 state_ = BmpDecodingState::IMAGE_DECODED;
325 ImageUtils::FlushContextSurfaceBuffer(context);
326 return SUCCESS;
327 }
328
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & context)329 uint32_t BmpDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
330 {
331 // currently not support increment decode
332 return ERR_IMAGE_DATA_UNSUPPORT;
333 }
334
DecodeHeader()335 bool BmpDecoder::DecodeHeader()
336 {
337 codec_ = SkCodec::MakeFromStream(make_unique<BmpStream>(stream_));
338 if (codec_ == nullptr) {
339 IMAGE_LOGE("create codec from stream failed");
340 return false;
341 }
342 info_ = codec_->getInfo();
343 return true;
344 }
345
ConvertToAlphaType(SkAlphaType alphaType)346 AlphaType BmpDecoder::ConvertToAlphaType(SkAlphaType alphaType)
347 {
348 switch (alphaType) {
349 case kOpaque_SkAlphaType:
350 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
351 case kPremul_SkAlphaType:
352 return AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
353 case kUnpremul_SkAlphaType:
354 return AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL;
355 default:
356 IMAGE_LOGE("unknown alpha type:%{public}d", alphaType);
357 break;
358 }
359 return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
360 }
361
ConvertToColorType(PixelFormat format,PixelFormat & outputFormat)362 SkColorType BmpDecoder::ConvertToColorType(PixelFormat format, PixelFormat &outputFormat)
363 {
364 switch (format) {
365 case PixelFormat::UNKNOWN:
366 case PixelFormat::RGBA_8888: {
367 outputFormat = PixelFormat::RGBA_8888;
368 return kRGBA_8888_SkColorType;
369 }
370 case PixelFormat::BGRA_8888: {
371 outputFormat = PixelFormat::BGRA_8888;
372 return kBGRA_8888_SkColorType;
373 }
374 case PixelFormat::ALPHA_8: {
375 SkColorType colorType = info_.colorType();
376 if (colorType == kAlpha_8_SkColorType || (colorType == kGray_8_SkColorType && info_.isOpaque())) {
377 outputFormat = PixelFormat::ALPHA_8;
378 return kAlpha_8_SkColorType;
379 }
380 break;
381 }
382 case PixelFormat::RGB_565: {
383 if (info_.isOpaque()) {
384 outputFormat = PixelFormat::RGB_565;
385 return kRGB_565_SkColorType;
386 }
387 break;
388 }
389 default: {
390 break;
391 }
392 }
393 IMAGE_LOGD("unsupported convert to format:%{public}d, set default RGBA", format);
394 outputFormat = PixelFormat::RGBA_8888;
395 return kRGBA_8888_SkColorType;
396 }
397 } // namespace ImagePlugin
398 } // namespace OHOS
399