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