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