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