1 /*
2  * Copyright (C) 2024 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 "auxiliary_generator.h"
17 #include "abs_image_decoder.h"
18 #include "fragment_metadata.h"
19 #include "hdr_type.h"
20 #include "image_log.h"
21 #include "image_utils.h"
22 #include "image_mime_type.h"
23 #include "image_source.h"
24 #include "jpeg_mpf_parser.h"
25 #include "metadata.h"
26 #include "pixel_map.h"
27 #include "pixel_yuv.h"
28 #ifdef EXT_PIXEL
29 #include "pixel_yuv_ext.h"
30 #endif
31 #include "securec.h"
32 #include "surface_buffer.h"
33 
34 namespace OHOS {
35 namespace Media {
36 using namespace ImagePlugin;
37 
38 static constexpr uint32_t FIRST_FRAME = 0;
39 static constexpr int32_t DEFAULT_SCALE_DENOMINATOR = 1;
40 static constexpr int32_t DEPTH_SCALE_DENOMINATOR = 4;
41 static constexpr int32_t LINEAR_SCALE_DENOMINATOR = 4;
42 
IsSizeVailed(const Size &size)43 static inline bool IsSizeVailed(const Size &size)
44 {
45     return (size.width != 0 && size.height != 0);
46 }
47 
GetAuxiliaryPictureDenominator(AuxiliaryPictureType type)48 static int32_t GetAuxiliaryPictureDenominator(AuxiliaryPictureType type)
49 {
50     int32_t denominator = DEFAULT_SCALE_DENOMINATOR;
51     switch (type) {
52         case AuxiliaryPictureType::DEPTH_MAP:
53             denominator = DEPTH_SCALE_DENOMINATOR;
54             break;
55         case AuxiliaryPictureType::LINEAR_MAP:
56             denominator = LINEAR_SCALE_DENOMINATOR;
57             break;
58         default:
59             break;
60     }
61     return denominator;
62 }
63 
SetAuxiliaryDecodeOption(std::unique_ptr<AbsImageDecoder> &decoder, PlImageInfo &plInfo, AuxiliaryPictureType type)64 static uint32_t SetAuxiliaryDecodeOption(std::unique_ptr<AbsImageDecoder> &decoder, PlImageInfo &plInfo,
65                                          AuxiliaryPictureType type)
66 {
67     Size size;
68     uint32_t errorCode = decoder->GetImageSize(FIRST_FRAME, size);
69     if (errorCode != SUCCESS || !IsSizeVailed(size)) {
70         return ERR_IMAGE_DATA_ABNORMAL;
71     }
72     PixelDecodeOptions plOptions;
73     plOptions.desiredSize = size;
74     bool useF16Format = (type == AuxiliaryPictureType::LINEAR_MAP || type == AuxiliaryPictureType::DEPTH_MAP);
75     plOptions.desiredPixelFormat = useF16Format ? PixelFormat::RGBA_F16 : PixelFormat::RGBA_8888;
76     errorCode = decoder->SetDecodeOptions(FIRST_FRAME, plOptions, plInfo);
77     return errorCode;
78 }
79 
FreeContextBuffer(const Media::CustomFreePixelMap &func, AllocatorType allocType, PlImageBuffer &buffer)80 static void FreeContextBuffer(const Media::CustomFreePixelMap &func, AllocatorType allocType, PlImageBuffer &buffer)
81 {
82     if (func != nullptr) {
83         func(buffer.buffer, buffer.context, buffer.bufferSize);
84         return;
85     }
86 
87 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
88     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
89         int *fd = static_cast<int *>(buffer.context);
90         if (buffer.buffer != nullptr) {
91             ::munmap(buffer.buffer, buffer.bufferSize);
92         }
93         if (fd != nullptr) {
94             ::close(*fd);
95         }
96         return;
97     } else if (allocType == AllocatorType::DMA_ALLOC) {
98         if (buffer.buffer != nullptr) {
99             ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer *>(buffer.context));
100             buffer.context = nullptr;
101         }
102     } else if (allocType == AllocatorType::HEAP_ALLOC) {
103         if (buffer.buffer != nullptr) {
104             free(buffer.buffer);
105             buffer.buffer = nullptr;
106         }
107     }
108 #else
109     if (buffer.buffer != nullptr) {
110         free(buffer.buffer);
111         buffer.buffer = nullptr;
112     }
113 #endif
114 }
115 
MakeImageInfo(const Size &size, PixelFormat format, AlphaType alphaType, ColorSpace colorSpace, const std::string &encodedFormat)116 static ImageInfo MakeImageInfo(const Size &size, PixelFormat format, AlphaType alphaType,
117     ColorSpace colorSpace, const std::string &encodedFormat)
118 {
119     ImageInfo info;
120     info.size.width = size.width;
121     info.size.height = size.height;
122     info.pixelFormat = format;
123     info.alphaType = alphaType;
124     info.colorSpace = colorSpace;
125     info.encodedFormat = encodedFormat;
126     return info;
127 }
128 
MakeAuxiliaryPictureInfo(AuxiliaryPictureType type, const Size &size, uint32_t rowStride, PixelFormat format, ColorSpace colorSpace)129 static AuxiliaryPictureInfo MakeAuxiliaryPictureInfo(AuxiliaryPictureType type,
130     const Size &size, uint32_t rowStride, PixelFormat format, ColorSpace colorSpace)
131 {
132     AuxiliaryPictureInfo info;
133     info.auxiliaryPictureType = type;
134     info.size.width = size.width;
135     info.size.height = size.height;
136     info.rowStride = rowStride;
137     info.pixelFormat = format;
138     info.colorSpace = colorSpace;
139     return info;
140 }
141 
CreatePixelMapByContext(DecodeContext &context, std::unique_ptr<AbsImageDecoder> &decoder, const std::string &encodedFormat, uint32_t &errorCode)142 static std::shared_ptr<PixelMap> CreatePixelMapByContext(DecodeContext &context,
143     std::unique_ptr<AbsImageDecoder> &decoder, const std::string &encodedFormat, uint32_t &errorCode)
144 {
145     std::shared_ptr<PixelMap> pixelMap;
146     if (ImageSource::IsYuvFormat(context.pixelFormat)) {
147 #ifdef EXT_PIXEL
148         pixelMap = std::make_shared<PixelYuvExt>();
149 #else
150         pixelMap = std::make_shared<PixelYuv>();
151 #endif
152     } else {
153         pixelMap = std::make_shared<PixelMap>();
154     }
155     if (pixelMap == nullptr) {
156         errorCode = ERR_IMAGE_ADD_PIXEL_MAP_FAILED;
157         return nullptr;
158     }
159 
160     ImageInfo imageinfo = MakeImageInfo(context.outInfo.size, context.pixelFormat,
161                                         context.info.alphaType, context.colorSpace, encodedFormat);
162     pixelMap->SetImageInfo(imageinfo, true);
163 
164     PixelMapAddrInfos addrInfos;
165     ImageSource::ContextToAddrInfos(context, addrInfos);
166     pixelMap->SetPixelsAddr(addrInfos.addr, addrInfos.context, addrInfos.size, addrInfos.type, addrInfos.func);
167 
168 #ifdef IMAGE_COLORSPACE_FLAG
169     if (context.hdrType > ImageHdrType::SDR) {
170         pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(context.grColorSpaceName));
171     } else if (decoder->IsSupportICCProfile()) {
172         pixelMap->InnerSetColorSpace(decoder->getGrColorSpace());
173     }
174 #endif
175     return pixelMap;
176 }
177 
DecodeHdrMetadata(ImageHdrType hdrType, std::unique_ptr<AbsImageDecoder> &extDecoder, std::unique_ptr<AuxiliaryPicture> &auxPicture)178 static uint32_t DecodeHdrMetadata(ImageHdrType hdrType, std::unique_ptr<AbsImageDecoder> &extDecoder,
179     std::unique_ptr<AuxiliaryPicture> &auxPicture)
180 {
181     std::shared_ptr<HdrMetadata> hdrMetadata = std::make_shared<HdrMetadata>(extDecoder->GetHdrMetadata(hdrType));
182     std::shared_ptr<PixelMap> pixelMap = auxPicture->GetContentPixel();
183     if (pixelMap == nullptr) {
184         IMAGE_LOGE("Get invalid content pixel map for hdr metadata");
185         return ERR_IMAGE_GET_DATA_ABNORMAL;
186     }
187     pixelMap->SetHdrMetadata(hdrMetadata);
188     pixelMap->SetHdrType(hdrType);
189     return SUCCESS;
190 }
191 
DecodeHeifFragmentMetadata(std::unique_ptr<AbsImageDecoder> &extDecoder, std::unique_ptr<AuxiliaryPicture> &auxPicture)192 static uint32_t DecodeHeifFragmentMetadata(std::unique_ptr<AbsImageDecoder> &extDecoder,
193     std::unique_ptr<AuxiliaryPicture> &auxPicture)
194 {
195     Rect fragmentRect;
196     if (!extDecoder->GetHeifFragmentMetadata(fragmentRect)) {
197         IMAGE_LOGE("Heif parsing fragment metadata failed");
198         return ERR_IMAGE_GET_DATA_ABNORMAL;
199     }
200     std::shared_ptr<ImageMetadata> fragmentMetadata = std::make_shared<FragmentMetadata>();
201     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_X, std::to_string(fragmentRect.left));
202     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_Y, std::to_string(fragmentRect.top));
203     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_WIDTH, std::to_string(fragmentRect.width));
204     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_HEIGHT, std::to_string(fragmentRect.height));
205     auxPicture->SetMetadata(MetadataType::FRAGMENT, fragmentMetadata);
206     return SUCCESS;
207 }
208 
DecodeJpegFragmentMetadata(std::unique_ptr<InputDataStream> &auxStream, std::unique_ptr<AuxiliaryPicture> &auxPicture)209 static uint32_t DecodeJpegFragmentMetadata(std::unique_ptr<InputDataStream> &auxStream,
210     std::unique_ptr<AuxiliaryPicture> &auxPicture)
211 {
212     uint8_t *data = auxStream->GetDataPtr();
213     uint32_t size = auxStream->GetStreamSize();
214     Rect fragmentRect;
215     if (!JpegMpfParser::ParsingFragmentMetadata(data, size, fragmentRect)) {
216         IMAGE_LOGE("Jpeg parsing fragment metadata failed");
217         return ERR_IMAGE_GET_DATA_ABNORMAL;
218     }
219     std::shared_ptr<ImageMetadata> fragmentMetadata = std::make_shared<FragmentMetadata>();
220     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_X, std::to_string(fragmentRect.left));
221     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_Y, std::to_string(fragmentRect.top));
222     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_WIDTH, std::to_string(fragmentRect.width));
223     fragmentMetadata->SetValue(FRAGMENT_METADATA_KEY_HEIGHT, std::to_string(fragmentRect.height));
224     auxPicture->SetMetadata(MetadataType::FRAGMENT, fragmentMetadata);
225     return SUCCESS;
226 }
227 
AllocSurfaceBuffer(Size &size, int32_t format, uint32_t &errorCode)228 static sptr<SurfaceBuffer> AllocSurfaceBuffer(Size &size, int32_t format, uint32_t &errorCode)
229 {
230     IMAGE_LOGD("SurfaceBuffer alloc width: %{public}d, height: %{public}d, format: %{public}d",
231         size.width, size.height, format);
232     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
233     BufferRequestConfig requestConfig = {
234         .width = size.width,
235         .height = size.height,
236         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
237         .format = format,
238         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
239         .timeout = 0,
240     };
241     GSError ret = sb->Alloc(requestConfig);
242     if (ret != GSERROR_OK) {
243         IMAGE_LOGE("SurfaceBuffer alloc failed, %{public}s", GSErrorStr(ret).c_str());
244         errorCode = ERR_DMA_NOT_EXIST;
245         return nullptr;
246     }
247     void *nativeBuffer = sb.GetRefPtr();
248     if (ImageUtils::SurfaceBuffer_Reference(nativeBuffer) != OHOS::GSERROR_OK) {
249         IMAGE_LOGE("Native buffer reference failed");
250         errorCode = ERR_SURFACEBUFFER_REFERENCE_FAILED;
251         return nullptr;
252     }
253     errorCode = SUCCESS;
254     return sb;
255 }
256 
CopyToSurfaceBuffer(std::unique_ptr<InputDataStream> &stream, sptr<SurfaceBuffer> &surfaceBuffer)257 static uint32_t CopyToSurfaceBuffer(std::unique_ptr<InputDataStream> &stream, sptr<SurfaceBuffer> &surfaceBuffer)
258 {
259     uint8_t *src = stream->GetDataPtr();
260     uint32_t srcSize = stream->GetStreamSize();
261     uint8_t *dst = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr());
262     uint32_t dstSize = surfaceBuffer->GetSize();
263     if (src == nullptr || dst == nullptr || srcSize == 0 || dstSize == 0) {
264         IMAGE_LOGE("%{public}s: invalid input data", __func__);
265         return ERR_IMAGE_INVALID_PARAMETER;
266     }
267     IMAGE_LOGD("SurfaceBuffer size: %{public}u, stream size: %{public}u", dstSize, srcSize);
268     if (memcpy_s(dst, dstSize, src, srcSize) != EOK) {
269         IMAGE_LOGE("%{public}s: memcpy failed", __func__);
270         ImageUtils::SurfaceBuffer_Unreference(surfaceBuffer.GetRefPtr());
271         return ERR_MEMORY_COPY_FAILED;
272     }
273     return SUCCESS;
274 }
275 
SetUncodedAuxilaryPictureInfo(std::unique_ptr<AuxiliaryPicture> &auxPicture)276 static void SetUncodedAuxilaryPictureInfo(std::unique_ptr<AuxiliaryPicture> &auxPicture)
277 {
278     if (auxPicture == nullptr || auxPicture->GetContentPixel() == nullptr) {
279         IMAGE_LOGE("%{public}s auxPicture or auxPixelMap is nullptr", __func__);
280         return;
281     }
282     auto auxPixelMap = auxPicture->GetContentPixel();
283     ImageInfo imageInfo;
284     auxPixelMap->GetImageInfo(imageInfo);
285     auto auxInfo = MakeAuxiliaryPictureInfo(auxPicture->GetType(), imageInfo.size, auxPixelMap->GetRowStride(),
286         imageInfo.pixelFormat, imageInfo.colorSpace);
287     auxPicture->SetAuxiliaryPictureInfo(auxInfo);
288 }
289 
GenerateAuxiliaryPicture(ImageHdrType hdrType, AuxiliaryPictureType type, const std::string &format, std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)290 static std::unique_ptr<AuxiliaryPicture> GenerateAuxiliaryPicture(ImageHdrType hdrType, AuxiliaryPictureType type,
291     const std::string &format, std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)
292 {
293     IMAGE_LOGI("Generate by decoder, type: %{public}d, format: %{public}s", static_cast<int>(type), format.c_str());
294     DecodeContext context;
295     context.allocatorType = AllocatorType::DMA_ALLOC;
296     errorCode = SetAuxiliaryDecodeOption(extDecoder, context.info, type);
297     if (errorCode != SUCCESS) {
298         IMAGE_LOGE("Set auxiliary decode option failed! errorCode: %{public}u", errorCode);
299         return nullptr;
300     }
301     if (format == IMAGE_HEIF_FORMAT) {
302 #ifdef HEIF_HW_DECODE_ENABLE
303         if (type == AuxiliaryPictureType::LINEAR_MAP || type == AuxiliaryPictureType::DEPTH_MAP) {
304             context.pixelFormat = PixelFormat::RGBA_F16;
305             context.info.pixelFormat = PixelFormat::RGBA_F16;
306         }
307         if (!extDecoder->DecodeHeifAuxiliaryMap(context, type)) {
308             errorCode = ERR_IMAGE_DECODE_FAILED;
309         }
310 #else
311         errorCode = ERR_IMAGE_HW_DECODE_UNSUPPORT;
312 #endif
313     } else if (format == IMAGE_JPEG_FORMAT) {
314         errorCode = extDecoder->Decode(FIRST_FRAME, context);
315         context.hdrType = hdrType;
316     } else {
317         errorCode = ERR_MEDIA_DATA_UNSUPPORT;
318     }
319     if (errorCode != SUCCESS) {
320         IMAGE_LOGE("Decode failed! Format: %{public}s, errorCode: %{public}u", format.c_str(), errorCode);
321         FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
322         return nullptr;
323     }
324 
325     std::string encodedFormat = ImageUtils::IsAuxiliaryPictureEncoded(type) ? format : "";
326     std::shared_ptr<PixelMap> pixelMap = CreatePixelMapByContext(context, extDecoder, encodedFormat, errorCode);
327     auto auxPicture = AuxiliaryPicture::Create(pixelMap, type, context.outInfo.size);
328     auxPicture->SetAuxiliaryPictureInfo(
329         MakeAuxiliaryPictureInfo(type, context.outInfo.size, pixelMap->GetRowStride(),
330                                  context.pixelFormat, context.outInfo.colorSpace));
331     return auxPicture;
332 }
333 
GenerateHeifAuxiliaryPicture(ImageHdrType hdrType, AuxiliaryPictureType type, std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)334 std::shared_ptr<AuxiliaryPicture> AuxiliaryGenerator::GenerateHeifAuxiliaryPicture(ImageHdrType hdrType,
335     AuxiliaryPictureType type, std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)
336 {
337     IMAGE_LOGI("Generate heif auxiliary picture, type: %{public}d", static_cast<int>(type));
338     if (!ImageUtils::IsAuxiliaryPictureTypeSupported(type) || extDecoder == nullptr) {
339         errorCode = ERR_IMAGE_INVALID_PARAMETER;
340         return nullptr;
341     }
342 
343     auto auxPicture = GenerateAuxiliaryPicture(hdrType, type, IMAGE_HEIF_FORMAT, extDecoder, errorCode);
344     if (errorCode != SUCCESS) {
345         IMAGE_LOGE("Generate heif auxiliary picture failed! errorCode: %{public}u", errorCode);
346         return nullptr;
347     }
348     if (type == AuxiliaryPictureType::GAINMAP) {
349         errorCode = DecodeHdrMetadata(hdrType, extDecoder, auxPicture);
350     } else if (type == AuxiliaryPictureType::FRAGMENT_MAP) {
351         errorCode = DecodeHeifFragmentMetadata(extDecoder, auxPicture);
352     }
353     if (errorCode != SUCCESS) {
354         IMAGE_LOGE("Decode heif metadata failed! errorCode: %{public}u", errorCode);
355         return nullptr;
356     }
357     return std::move(auxPicture);
358 }
359 
GenerateJpegAuxiliaryPicture( const MainPictureInfo &mainInfo, AuxiliaryPictureType type, std::unique_ptr<InputDataStream> &auxStream, std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)360 std::shared_ptr<AuxiliaryPicture> AuxiliaryGenerator::GenerateJpegAuxiliaryPicture(
361     const MainPictureInfo &mainInfo, AuxiliaryPictureType type, std::unique_ptr<InputDataStream> &auxStream,
362     std::unique_ptr<AbsImageDecoder> &extDecoder, uint32_t &errorCode)
363 {
364     IMAGE_LOGI("Generate jpeg auxiliary picture, type: %{public}d", static_cast<int>(type));
365     if (!ImageUtils::IsAuxiliaryPictureTypeSupported(type) || auxStream == nullptr || extDecoder == nullptr) {
366         errorCode = ERR_IMAGE_INVALID_PARAMETER;
367         return nullptr;
368     }
369 
370     if (ImageUtils::IsAuxiliaryPictureEncoded(type)) {
371         auto auxPicture = GenerateAuxiliaryPicture(mainInfo.hdrType, type, IMAGE_JPEG_FORMAT, extDecoder, errorCode);
372         if (errorCode != SUCCESS) {
373             IMAGE_LOGE("Generate jpeg auxiliary picture failed! errorCode: %{public}u", errorCode);
374             return nullptr;
375         }
376         if (type == AuxiliaryPictureType::GAINMAP) {
377             errorCode = DecodeHdrMetadata(mainInfo.hdrType, extDecoder, auxPicture);
378         } else if (type == AuxiliaryPictureType::FRAGMENT_MAP) {
379             errorCode = DecodeJpegFragmentMetadata(auxStream, auxPicture);
380         }
381         if (errorCode != SUCCESS) {
382             IMAGE_LOGE("Decode jpeg metadata failed! errorCode: %{public}u", errorCode);
383             return nullptr;
384         }
385         return auxPicture;
386     }
387 
388     int32_t denominator = GetAuxiliaryPictureDenominator(type);
389     denominator = (denominator == 0) ? DEFAULT_SCALE_DENOMINATOR : denominator;
390     Size size = {mainInfo.imageInfo.size.width / denominator, mainInfo.imageInfo.size.height / denominator};
391     sptr<SurfaceBuffer> surfaceBuffer = AllocSurfaceBuffer(size, GRAPHIC_PIXEL_FMT_RGBA16_FLOAT, errorCode);
392     if (errorCode != SUCCESS || surfaceBuffer == nullptr) {
393         IMAGE_LOGE("Alloc surface buffer failed! errorCode: %{public}u", errorCode);
394         return nullptr;
395     }
396     errorCode = CopyToSurfaceBuffer(auxStream, surfaceBuffer);
397     if (errorCode != SUCCESS) {
398         IMAGE_LOGE("Convert stream to surface buffer failed! errorCode: %{public}u", errorCode);
399         return nullptr;
400     }
401     auto auxPicture = AuxiliaryPicture::Create(surfaceBuffer, type, size);
402     SetUncodedAuxilaryPictureInfo(auxPicture);
403     return auxPicture;
404 }
405 
406 } // namespace Media
407 } // namespace OHOS
408