• 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 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 "encode_heif_helper.h"
17 
18 namespace OHOS::VDI::HEIF {
19 using namespace OHOS::HDI::Codec::Image::V2_1;
20 using namespace std;
21 
22 enum ValueOption : uint8_t {
23     OPTION_0 = 0,
24     OPTION_1,
25     OPTION_2,
26     OPTION_3,
27     OPTION_BUTT
28 };
29 
AllocOutputBuffer(SharedBuffer & output)30 bool HeifEncodeHelper::AllocOutputBuffer(SharedBuffer& output)
31 {
32     static constexpr size_t EXTERNAL_BUFFER_SIZE = 18 * 1024 * 1024;
33     int fd = AshmemCreate("ForHeifEditOut", EXTERNAL_BUFFER_SIZE);
34     bool flag = true;
35     if (fd >= 0) {
36         output.fd = fd;
37         output.capacity = static_cast<uint32_t>(AshmemGetSize(fd));
38     } else {
39         flag = false;
40         output.fd = -1;
41         output.capacity = 0;
42         HDF_LOGE("failed to create output buffer");
43     }
44     output.filledLen = 0;
45     return flag;
46 }
47 
48 
Reset()49 void HeifEncodeHelper::Reset()
50 {
51     inputImgs_.clear();
52     inputMetas_.clear();
53     refs_.clear();
54 }
55 
FillRefItem(ItemRef item,uint8_t * data,size_t & size)56 ItemRef HeifEncodeHelper::FillRefItem(ItemRef item, uint8_t *data, size_t &size)
57 {
58     uint8_t *dataEnd = data + size - 1;
59     if (dataEnd < (data + sizeof(uint8_t))) {
60         return item;
61     }
62 
63     switch ((*data) % OPTION_BUTT) {
64         case OPTION_0:
65             item.type = DIMG;
66             break;
67         case OPTION_1:
68             item.type = THMB;
69             break;
70         case OPTION_2:
71             item.type = AUXL;
72             break;
73         case OPTION_3:
74             item.type = CDSC;
75             break;
76     }
77     data += sizeof(uint8_t);
78     size -= sizeof(uint8_t);
79 
80     if (dataEnd < data + sizeof(item.from)) {
81         return item;
82     }
83     item.from = ToUint32(data);
84     data += sizeof(item.from);
85     size -= sizeof(item.from);
86 
87     if (dataEnd < data + sizeof(uint8_t)) {
88         return item;
89     }
90     uint8_t vecSize = (*data) % 2 + 1;
91     data += sizeof(vecSize);
92     size -= sizeof(vecSize);
93     if (dataEnd < (data + vecSize * sizeof(item.from))) {
94         return item;
95     } else {
96         while (vecSize--) {
97             item.to.emplace_back(ToUint32(data));
98             data += sizeof(item.from);
99             size -= sizeof(item.from);
100         }
101     }
102     return item;
103 }
104 
FillImageItem(ImgType type,ImageItem & item,uint8_t * data,size_t & size)105 bool HeifEncodeHelper::FillImageItem(ImgType type, ImageItem& item, uint8_t *data, size_t &size)
106 {
107     uint8_t *dataEnd = data + size - 1;
108     item.itemName = "";
109     if (dataEnd < data + sizeof(item.id) + sizeof(item.quality) + sizeof(uint8_t)) {
110         return false;
111     }
112     item.id = ToUint32(data);
113     data += sizeof(item.id);
114     size -= sizeof(item.id);
115 
116     item.pixelBuffer = bufferHelper_.CreateImgBuffer(data, size);
117     IF_TRUE_RETURN_VAL((type != T_MAP && item.pixelBuffer == nullptr), false);
118     item.isPrimary = (type == PRIMARY_IMG);
119     item.isHidden = (type != PRIMARY_IMG);
120     item.compressType = (type == T_MAP ? "none" : "hevc");
121 
122     item.quality = ToUint32(data);
123     data += sizeof(item.quality);
124     size -= sizeof(item.quality);
125 
126     item.liteProperties = {};
127     uint8_t liteProSize = *data;
128     data += sizeof(liteProSize);
129     size -= sizeof(liteProSize);
130 
131     if (dataEnd < data + liteProSize) {
132         return false;
133     }
134 
135     HDF_LOGI("Fill Image LiteProperties");
136     while (liteProSize--) {
137         item.liteProperties.push_back(*data);
138         data += sizeof(uint8_t);
139         size -= sizeof(uint8_t);
140     }
141 
142     item.sharedProperties = {
143         .fd = -1,
144         .filledLen = 0,
145         .capacity = 0
146     };
147 
148     if (dataEnd < (data + sizeof(uint8_t))) {
149         return false;
150     }
151     uint8_t decision = (*data) % 2;
152     data += sizeof(decision);
153     size -= sizeof(decision);
154     if (decision) {
155         HDF_LOGI("Fill Image SharedProperties");
156         item.sharedProperties = bufferHelper_.CreateSharedBuffer(data, size);
157     }
158     return true;
159 }
160 
AssembleParamForOtherImg(uint32_t primaryImgId,uint8_t * data,size_t & size)161 bool HeifEncodeHelper::AssembleParamForOtherImg(uint32_t primaryImgId, uint8_t *data, size_t &size)
162 {
163     uint8_t *dataEnd = data + size - 1;
164     if (dataEnd < data + sizeof(uint8_t)) {
165         return false;
166     }
167     uint8_t decision = (*data) % 2;
168     data += sizeof(uint8_t);
169     size -= sizeof(uint8_t);
170 
171     if (decision == 1) {
172         ImageItem itemAuxlImg;
173         HDF_LOGI("Fill itemAuxlImg");
174         if (!FillImageItem(AUXILIARY_IMG, itemAuxlImg, data, size)) {
175             HDF_LOGE("%{public}s: Fill itemAuxlImg failed\n", __func__);
176             return false;
177         }
178         HDF_LOGI("Fill itemAuxlImg Succesfully");
179         inputImgs_.emplace_back(itemAuxlImg);
180         ItemRef refAuxl = {
181             .type = AUXL,
182             .auxType = "",
183             .from = itemAuxlImg.id,
184             .to = {primaryImgId}
185         };
186         ItemRef newRefAulx = FillRefItem(refAuxl, data, size);
187         refs_.emplace_back(newRefAulx);
188     } else {
189         ImageItem itemThmbImg;
190         HDF_LOGI("Fill itemThmbImg");
191         if (!FillImageItem(THUMBNAIL_IMG, itemThmbImg, data, size)) {
192             HDF_LOGE("%{public}s: Fill itemThmbImg failed\n", __func__);
193             return false;
194         }
195         HDF_LOGI("Fill itemThmbImg Succesfully");
196         inputImgs_.emplace_back(itemThmbImg);
197 
198         ItemRef refThmb = {
199             .type = THMB,
200             .auxType = "",
201             .from = itemThmbImg.id,
202             .to = {primaryImgId}
203         };
204         ItemRef newRefThmb = FillRefItem(refThmb, data, size);
205         refs_.emplace_back(newRefThmb);
206     }
207     return true;
208 }
209 
AssembleParamForTmap(uint8_t * data,size_t & size)210 bool HeifEncodeHelper::AssembleParamForTmap(uint8_t *data, size_t &size)
211 {
212     ImageItem itemTmap;
213     ImageItem itemPrimaryImg;
214     ImageItem itemGainMap;
215     HDF_LOGI("AssembleParamForTmap: Fill ImageItem");
216     if (!FillImageItem(T_MAP, itemTmap, data, size)) {
217         HDF_LOGE("%{public}s: Fill itemTmap failed\n", __func__);
218         return false;
219     }
220 
221     if (!FillImageItem(PRIMARY_IMG, itemPrimaryImg, data, size)) {
222         HDF_LOGE("%{public}s: Fill itemPrimaryImg failed\n", __func__);
223         return false;
224     }
225 
226     if (!FillImageItem(GAIN_MAP, itemGainMap, data, size)) {
227         HDF_LOGE("%{public}s: Fill itemGainMap failed\n", __func__);
228         return false;
229     }
230     inputImgs_.emplace_back(itemTmap);
231     inputImgs_.emplace_back(itemPrimaryImg);
232     inputImgs_.emplace_back(itemGainMap);
233 
234     ItemRef refTMap = {
235         .type = DIMG,
236         .auxType = "",
237         .from = itemTmap.id,
238         .to = {itemPrimaryImg.id, itemGainMap.id}
239     };
240 
241     HDF_LOGI("AssembleParamForTmap: Fill RefItem");
242     ItemRef newRefTMap = FillRefItem(refTMap, data, size);
243     refs_.emplace_back(newRefTMap);
244 
245     HDF_LOGI("AssembleParamForTmap: Fill OtherImg");
246     if (AssembleParamForOtherImg(itemPrimaryImg.id, data, size)) {
247         HDF_LOGI("AssembleParamForTmap: Fill MetaData");
248         return AssembleParamForMetaData(itemPrimaryImg.id, data, size);
249     }
250     return false;
251 }
252 
AssembleParamForPrimaryImg(uint8_t * data,size_t & size)253 bool HeifEncodeHelper::AssembleParamForPrimaryImg(uint8_t *data, size_t &size)
254 {
255     ImageItem itemPrimaryImg;
256     HDF_LOGI("AssembleParamForPrimaryImg: Fill ImageItem");
257     if (!FillImageItem(PRIMARY_IMG, itemPrimaryImg, data, size)) {
258         HDF_LOGE("%{public}s: Fill itemPrimaryImg failed\n", __func__);
259         return false;
260     }
261     inputImgs_.emplace_back(itemPrimaryImg);
262     HDF_LOGI("AssembleParamForPrimaryImg: Fill OtherImg");
263     if (AssembleParamForOtherImg(itemPrimaryImg.id, data, size)) {
264         HDF_LOGI("AssembleParamForPrimaryImg: Fill MetaData");
265         return AssembleParamForMetaData(itemPrimaryImg.id, data, size);
266     }
267     return true;
268 }
269 
FillMetaItem(MetaType type,MetaItem & item,uint8_t * data,size_t & size)270 bool HeifEncodeHelper::FillMetaItem(MetaType type, MetaItem& item, uint8_t *data, size_t &size)
271 {
272     uint8_t *dataEnd = data + size - 1;
273     item.itemName = "";
274     if (dataEnd < data + sizeof(item.id)) {
275         return false;
276     }
277     item.id = ToUint32(data);
278     data += sizeof(item.id);
279     size -= sizeof(item.id);
280     item.properties = {};
281 
282     if (type == USER_DATA) {
283         static constexpr char USER_DATA_LABEL[] = "userdata";
284         item.itemName = USER_DATA_LABEL;
285 
286         if (dataEnd < data + sizeof(uint8_t)) {
287             return false;
288         }
289         uint8_t propertiesSize = *data;
290         data += sizeof(propertiesSize);
291         size -= sizeof(propertiesSize);
292 
293         if (dataEnd < data + propertiesSize) {
294             return false;
295         }
296 
297         while (propertiesSize--) {
298             item.properties.emplace_back(*data);
299             data += sizeof(uint8_t);
300             size -= sizeof(uint8_t);
301         }
302     } else if (type == EXIF_DATA) {
303         static constexpr char EXIF_LABEL[] = "exif";
304         item.itemName = EXIF_LABEL;
305     }
306     item.data = bufferHelper_.CreateSharedBuffer(data, size);
307     return (item.data.fd >= 0);
308 }
309 
AssembleParamForMetaData(uint32_t primaryImgId,uint8_t * data,size_t & size)310 bool HeifEncodeHelper::AssembleParamForMetaData(uint32_t primaryImgId, uint8_t *data, size_t &size)
311 {
312     HDF_LOGI("AssembleParamForMetaData");
313     uint8_t* dataEnd = data + size - 1;
314     if (dataEnd < data + sizeof(uint8_t)) {
315         return false;
316     }
317     uint8_t decision = (*data) % 2;
318     data += sizeof(decision);
319     size -= sizeof(decision);
320     if (decision) {
321         HDF_LOGI("add exif");
322         MetaItem metaExifData;
323         HDF_LOGI("Fill Meta Item");
324         IF_TRUE_RETURN_VAL(!FillMetaItem(EXIF_DATA, metaExifData, data, size), false);
325         inputMetas_.emplace_back(metaExifData);
326         ItemRef refItem1 = {
327             .type = CDSC,
328             .auxType = "",
329             .from = metaExifData.id,
330             .to = {primaryImgId}
331         } ;
332         ItemRef newRefIt1 = FillRefItem(refItem1, data, size);
333         refs_.emplace_back(newRefIt1);
334         HDF_LOGI("Fill EXIF Data Succesfully");
335     } else {
336         HDF_LOGI("add userData");
337         MetaItem metaUserData;
338         HDF_LOGI("Fill Meta Item");
339         IF_TRUE_RETURN_VAL(!FillMetaItem(USER_DATA, metaUserData, data, size), false);
340         inputMetas_.emplace_back(metaUserData);
341         ItemRef refItem2 = {
342             .type = CDSC,
343             .auxType = "",
344             .from = metaUserData.id,
345             .to = {primaryImgId}
346         } ;
347         ItemRef newRefIt2 = FillRefItem(refItem2, data, size);
348         refs_.emplace_back(newRefIt2);
349         HDF_LOGI("Fill USER Data Succesfully");
350     }
351     return true;
352 }
353 
354 }
355