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