1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong DID Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci * 		http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "codec_jpeg_helper.h"
17094332d3Sopenharmony_ci#include <ashmem.h>
18094332d3Sopenharmony_ci#include <cerrno>
19094332d3Sopenharmony_ci#include <cstring>
20094332d3Sopenharmony_ci#include <securec.h>
21094332d3Sopenharmony_ci#include "hdf_log.h"
22094332d3Sopenharmony_ci
23094332d3Sopenharmony_cistatic int8_t UnZigZagTable[64] = {
24094332d3Sopenharmony_ci    0,  1,  5,  6, 14, 15, 27, 28,
25094332d3Sopenharmony_ci    2,  4,  7, 13, 16, 26, 29, 42,
26094332d3Sopenharmony_ci    3,  8, 12, 17, 25, 30, 41, 43,
27094332d3Sopenharmony_ci    9, 11, 18, 24, 31, 40, 44, 53,
28094332d3Sopenharmony_ci    10, 19, 23, 32, 39, 45, 52, 54,
29094332d3Sopenharmony_ci    20, 22, 33, 38, 46, 51, 55, 60,
30094332d3Sopenharmony_ci    21, 34, 37, 47, 50, 56, 59, 61,
31094332d3Sopenharmony_ci    35, 36, 48, 49, 57, 58, 62, 63};
32094332d3Sopenharmony_ci
33094332d3Sopenharmony_ciusing namespace OHOS::HDI::Codec::Image::V2_0;
34094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t fd)
35094332d3Sopenharmony_ci{
36094332d3Sopenharmony_ci    HDF_LOGI("enter");
37094332d3Sopenharmony_ci    int32_t curPos = 0;
38094332d3Sopenharmony_ci    // SOI
39094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffd8);
40094332d3Sopenharmony_ci    if (curPos < 0) {
41094332d3Sopenharmony_ci        HDF_LOGE("assemble SOI error");
42094332d3Sopenharmony_ci        return -1;
43094332d3Sopenharmony_ci    }
44094332d3Sopenharmony_ci
45094332d3Sopenharmony_ci    // DQT
46094332d3Sopenharmony_ci    curPos = JpegDqtAssemble(decInfo, buffer, curPos);
47094332d3Sopenharmony_ci    if (curPos < 0) {
48094332d3Sopenharmony_ci        HDF_LOGE("assemble DQT error");
49094332d3Sopenharmony_ci        return -1;
50094332d3Sopenharmony_ci    }
51094332d3Sopenharmony_ci
52094332d3Sopenharmony_ci    // DHT
53094332d3Sopenharmony_ci    curPos = JpegDhtAssemble(decInfo, buffer, curPos);
54094332d3Sopenharmony_ci    if (curPos < 0) {
55094332d3Sopenharmony_ci        HDF_LOGE("assemble DHT error");
56094332d3Sopenharmony_ci        return -1;
57094332d3Sopenharmony_ci    }
58094332d3Sopenharmony_ci    // DRI
59094332d3Sopenharmony_ci    curPos = JpegDriAssemble(decInfo, buffer, curPos);
60094332d3Sopenharmony_ci    if (curPos < 0) {
61094332d3Sopenharmony_ci        HDF_LOGE("assemble DRI error");
62094332d3Sopenharmony_ci        return -1;
63094332d3Sopenharmony_ci    }
64094332d3Sopenharmony_ci
65094332d3Sopenharmony_ci    // SOF
66094332d3Sopenharmony_ci    curPos = JpegSofAssemble(decInfo, buffer, curPos);
67094332d3Sopenharmony_ci    if (curPos < 0) {
68094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF error");
69094332d3Sopenharmony_ci        return -1;
70094332d3Sopenharmony_ci    }
71094332d3Sopenharmony_ci    // SOS
72094332d3Sopenharmony_ci    curPos = JpegSosAssemble(decInfo, buffer, curPos);
73094332d3Sopenharmony_ci    if (curPos < 0) {
74094332d3Sopenharmony_ci        HDF_LOGE("assemble SOS error");
75094332d3Sopenharmony_ci        return -1;
76094332d3Sopenharmony_ci    }
77094332d3Sopenharmony_ci    // DATA
78094332d3Sopenharmony_ci    curPos = JpegDataAssemble(buffer, curPos, fd);
79094332d3Sopenharmony_ci    if (curPos < 0) {
80094332d3Sopenharmony_ci        HDF_LOGE("assemble CompressedData error");
81094332d3Sopenharmony_ci        return -1;
82094332d3Sopenharmony_ci    }
83094332d3Sopenharmony_ci    // EOI
84094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffd9);
85094332d3Sopenharmony_ci    if (curPos < 0) {
86094332d3Sopenharmony_ci        HDF_LOGE("assemble EOI error");
87094332d3Sopenharmony_ci        return -1;
88094332d3Sopenharmony_ci    }
89094332d3Sopenharmony_ci    return curPos;
90094332d3Sopenharmony_ci}
91094332d3Sopenharmony_ci
92094332d3Sopenharmony_cibool CodecJpegHelper::DessambleJpeg(int8_t *buffer, size_t bufferLen, struct CodecJpegDecInfo &decInfo,
93094332d3Sopenharmony_ci                                    std::unique_ptr<int8_t[]> &compressBuffer, uint32_t &comBufLen, uint32_t &dataStart)
94094332d3Sopenharmony_ci{
95094332d3Sopenharmony_ci    HDF_LOGI("enter");
96094332d3Sopenharmony_ci    int8_t *start = buffer;
97094332d3Sopenharmony_ci    const int8_t *end = buffer + bufferLen;
98094332d3Sopenharmony_ci    while (start < end) {
99094332d3Sopenharmony_ci        JpegMarker marker = (JpegMarker)FindMarker(start);
100094332d3Sopenharmony_ci        start += 2;  // 2: marker len
101094332d3Sopenharmony_ci        switch (marker) {
102094332d3Sopenharmony_ci            case SOI:
103094332d3Sopenharmony_ci            case EOI:
104094332d3Sopenharmony_ci                break;
105094332d3Sopenharmony_ci            case SOF0:
106094332d3Sopenharmony_ci                start += DessambleSof(start, decInfo);
107094332d3Sopenharmony_ci                break;
108094332d3Sopenharmony_ci            case DHT:
109094332d3Sopenharmony_ci                start += DessambleDht(start, decInfo);
110094332d3Sopenharmony_ci                break;
111094332d3Sopenharmony_ci            case SOS: {
112094332d3Sopenharmony_ci                start += DessambleSos(start, decInfo);
113094332d3Sopenharmony_ci                dataStart = start - buffer;
114094332d3Sopenharmony_ci                // compressed data start
115094332d3Sopenharmony_ci                auto len = DessambleCompressData(start, compressBuffer, comBufLen);
116094332d3Sopenharmony_ci                if (len < 0) {
117094332d3Sopenharmony_ci                    HDF_LOGE("copy compressed data error");
118094332d3Sopenharmony_ci                    return false;
119094332d3Sopenharmony_ci                }
120094332d3Sopenharmony_ci                start += len;
121094332d3Sopenharmony_ci                break;
122094332d3Sopenharmony_ci            }
123094332d3Sopenharmony_ci
124094332d3Sopenharmony_ci            case DQT:
125094332d3Sopenharmony_ci                start += DessambleDqt(start, decInfo);
126094332d3Sopenharmony_ci                break;
127094332d3Sopenharmony_ci            case DRI: {
128094332d3Sopenharmony_ci                start += 2;  // 2: marker len
129094332d3Sopenharmony_ci                decInfo.restartInterval = GetInt16(start);
130094332d3Sopenharmony_ci                start += 2;  // 2: interval len
131094332d3Sopenharmony_ci                break;
132094332d3Sopenharmony_ci            }
133094332d3Sopenharmony_ci            default: {
134094332d3Sopenharmony_ci                short len = GetInt16(start);
135094332d3Sopenharmony_ci                start += len;
136094332d3Sopenharmony_ci                HDF_LOGW("skip marker[%{public}x], len[%{public}d]", marker, len);
137094332d3Sopenharmony_ci                break;
138094332d3Sopenharmony_ci            }
139094332d3Sopenharmony_ci        }
140094332d3Sopenharmony_ci    }
141094332d3Sopenharmony_ci    return true;
142094332d3Sopenharmony_ci}
143094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegDqtAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t curPos)
144094332d3Sopenharmony_ci{
145094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
146094332d3Sopenharmony_ci    // flag
147094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffdb);
148094332d3Sopenharmony_ci    if (curPos < 0) {
149094332d3Sopenharmony_ci        HDF_LOGE("assemble DQT flag error");
150094332d3Sopenharmony_ci        return curPos;
151094332d3Sopenharmony_ci    }
152094332d3Sopenharmony_ci
153094332d3Sopenharmony_ci    // skip len first
154094332d3Sopenharmony_ci    int32_t lenPos = curPos;
155094332d3Sopenharmony_ci    curPos += 2;  // 2: marker len
156094332d3Sopenharmony_ci
157094332d3Sopenharmony_ci    // data
158094332d3Sopenharmony_ci    for (size_t i = 0; i < decInfo.quantTbl.size(); i++) {
159094332d3Sopenharmony_ci        if (!decInfo.quantTbl[i].tableFlag) {
160094332d3Sopenharmony_ci            break;
161094332d3Sopenharmony_ci        }
162094332d3Sopenharmony_ci        uint8_t index = 0;         // precision 1:16bit, 0: 8bit, deault:1
163094332d3Sopenharmony_ci        index = (index << 4) | i;  // precision << 4 | tableid
164094332d3Sopenharmony_ci        curPos = PutInt8(buffer, curPos, index);
165094332d3Sopenharmony_ci        if (curPos < 0) {
166094332d3Sopenharmony_ci            HDF_LOGE("assemble precision and tableid error");
167094332d3Sopenharmony_ci            return curPos;
168094332d3Sopenharmony_ci        }
169094332d3Sopenharmony_ci
170094332d3Sopenharmony_ci        for (size_t j = 0; j < decInfo.quantTbl[i].quantVal.size(); j++) {
171094332d3Sopenharmony_ci            HDF_LOGI("decInfo.quantTbl[%{public}zu].quantVal[%{public}zu] = %{public}d", i, j,
172094332d3Sopenharmony_ci                decInfo.quantTbl[i].quantVal[j]);
173094332d3Sopenharmony_ci            curPos = PutInt16(buffer, curPos, decInfo.quantTbl[i].quantVal[j]);
174094332d3Sopenharmony_ci        }
175094332d3Sopenharmony_ci    }
176094332d3Sopenharmony_ci    int16_t bufferLen = static_cast<int16_t>(curPos - lenPos);
177094332d3Sopenharmony_ci    auto ret = PutInt16(buffer, lenPos, bufferLen);
178094332d3Sopenharmony_ci    if (ret < 0) {
179094332d3Sopenharmony_ci        HDF_LOGE("assemble len error");
180094332d3Sopenharmony_ci        return ret;
181094332d3Sopenharmony_ci    }
182094332d3Sopenharmony_ci    return curPos;
183094332d3Sopenharmony_ci}
184094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegDriAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t curPos)
185094332d3Sopenharmony_ci{
186094332d3Sopenharmony_ci    HDF_LOGI("enter, restartInterval = %{public}d curPos = %{public}d", decInfo.restartInterval, curPos);
187094332d3Sopenharmony_ci    if (decInfo.restartInterval <= 0) {
188094332d3Sopenharmony_ci        return curPos;
189094332d3Sopenharmony_ci    }
190094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffdd);
191094332d3Sopenharmony_ci    if (curPos < 0) {
192094332d3Sopenharmony_ci        HDF_LOGE("assemble DRI flag error");
193094332d3Sopenharmony_ci        return curPos;
194094332d3Sopenharmony_ci    }
195094332d3Sopenharmony_ci
196094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 4);  // 4: dri data len( marker len included)
197094332d3Sopenharmony_ci    if (curPos < 0) {
198094332d3Sopenharmony_ci        HDF_LOGE("assemble DRI len error");
199094332d3Sopenharmony_ci        return curPos;
200094332d3Sopenharmony_ci    }
201094332d3Sopenharmony_ci
202094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, decInfo.restartInterval);
203094332d3Sopenharmony_ci    if (curPos < 0) {
204094332d3Sopenharmony_ci        HDF_LOGE("assemble dri value error");
205094332d3Sopenharmony_ci        return curPos;
206094332d3Sopenharmony_ci    }
207094332d3Sopenharmony_ci    return curPos;
208094332d3Sopenharmony_ci}
209094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegDhtAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t curPos)
210094332d3Sopenharmony_ci{
211094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
212094332d3Sopenharmony_ci    curPos = JpegDhtAssemble(decInfo.dcHuffTbl, buffer, curPos);
213094332d3Sopenharmony_ci    if (curPos < 0) {
214094332d3Sopenharmony_ci        HDF_LOGE("assemble dc hufman error");
215094332d3Sopenharmony_ci        return curPos;
216094332d3Sopenharmony_ci    }
217094332d3Sopenharmony_ci
218094332d3Sopenharmony_ci    curPos = JpegDhtAssemble(decInfo.acHuffTbl, buffer, curPos, false);
219094332d3Sopenharmony_ci    if (curPos < 0) {
220094332d3Sopenharmony_ci        HDF_LOGE("assemble ac hufman error");
221094332d3Sopenharmony_ci    }
222094332d3Sopenharmony_ci    return curPos;
223094332d3Sopenharmony_ci}
224094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegDhtAssemble(const std::vector<CodecJpegHuffTable> &table, int8_t *buffer, int32_t curPos,
225094332d3Sopenharmony_ci                                         bool dc)
226094332d3Sopenharmony_ci{
227094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
228094332d3Sopenharmony_ci    // DC Hufman
229094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffc4);
230094332d3Sopenharmony_ci    if (curPos < 0) {
231094332d3Sopenharmony_ci        HDF_LOGE("assemble hufman flag error");
232094332d3Sopenharmony_ci        return curPos;
233094332d3Sopenharmony_ci    }
234094332d3Sopenharmony_ci    // skip len
235094332d3Sopenharmony_ci    int32_t lenPos = curPos;
236094332d3Sopenharmony_ci    curPos += 2;  // 2: marker len
237094332d3Sopenharmony_ci    for (size_t i = 0; i < table.size(); i++) {
238094332d3Sopenharmony_ci        if (!table[i].tableFlag) {
239094332d3Sopenharmony_ci            break;
240094332d3Sopenharmony_ci        }
241094332d3Sopenharmony_ci        uint8_t type = 0;  // type  0:DC, 1:AC
242094332d3Sopenharmony_ci        if (!dc) {
243094332d3Sopenharmony_ci            type = 1;
244094332d3Sopenharmony_ci        }
245094332d3Sopenharmony_ci        type = (type << 4) | i;  // type << 4 | tableid
246094332d3Sopenharmony_ci        curPos = PutInt8(buffer, curPos, type);
247094332d3Sopenharmony_ci        if (curPos < 0) {
248094332d3Sopenharmony_ci            HDF_LOGE("assemble tableid and dc/ac error");
249094332d3Sopenharmony_ci            return curPos;
250094332d3Sopenharmony_ci        }
251094332d3Sopenharmony_ci        // bits
252094332d3Sopenharmony_ci        auto ret = memcpy_s(buffer + curPos, table[i].bits.size(), table[i].bits.data(), table[i].bits.size());
253094332d3Sopenharmony_ci        if (ret != EOK) {
254094332d3Sopenharmony_ci            char buf[MAX_BUFFER_LEN] = {0};
255094332d3Sopenharmony_ci            strerror_r(errno, buf, sizeof(buf));
256094332d3Sopenharmony_ci            HDF_LOGE("assemble bits error ret = %{public}s", buf);
257094332d3Sopenharmony_ci            return ret;
258094332d3Sopenharmony_ci        }
259094332d3Sopenharmony_ci        curPos += table[i].bits.size();
260094332d3Sopenharmony_ci        // val
261094332d3Sopenharmony_ci        ret = memcpy_s(buffer + curPos, table[i].huffVal.size(), table[i].huffVal.data(), table[i].huffVal.size());
262094332d3Sopenharmony_ci        if (ret != EOK) {
263094332d3Sopenharmony_ci            HDF_LOGE("assemble huffVal error, ret = %{public}d", ret);
264094332d3Sopenharmony_ci            return ret;
265094332d3Sopenharmony_ci        }
266094332d3Sopenharmony_ci        curPos += table[i].huffVal.size();
267094332d3Sopenharmony_ci    }
268094332d3Sopenharmony_ci    int16_t bufferLen = static_cast<int16_t>(curPos - lenPos);
269094332d3Sopenharmony_ci    auto ret = PutInt16(buffer, lenPos, bufferLen);
270094332d3Sopenharmony_ci    if (ret < 0) {
271094332d3Sopenharmony_ci        HDF_LOGE("assemble len error");
272094332d3Sopenharmony_ci        return ret;
273094332d3Sopenharmony_ci    }
274094332d3Sopenharmony_ci    return curPos;
275094332d3Sopenharmony_ci}
276094332d3Sopenharmony_ci
277094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegSofAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t curPos)
278094332d3Sopenharmony_ci{
279094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
280094332d3Sopenharmony_ci    // flag
281094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffc0);
282094332d3Sopenharmony_ci    if (curPos < 0) {
283094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF flag error");
284094332d3Sopenharmony_ci        return curPos;
285094332d3Sopenharmony_ci    }
286094332d3Sopenharmony_ci
287094332d3Sopenharmony_ci    int16_t len = decInfo.numComponents * 3 + 8; // * rgb channel + other data
288094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, len);
289094332d3Sopenharmony_ci    if (curPos < 0) {
290094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF len error");
291094332d3Sopenharmony_ci        return curPos;
292094332d3Sopenharmony_ci    }
293094332d3Sopenharmony_ci
294094332d3Sopenharmony_ci    int8_t precision = decInfo.dataPrecision & 0xFF;
295094332d3Sopenharmony_ci    curPos = PutInt8(buffer, curPos, precision);
296094332d3Sopenharmony_ci    if (curPos < 0) {
297094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF precision error");
298094332d3Sopenharmony_ci        return curPos;
299094332d3Sopenharmony_ci    }
300094332d3Sopenharmony_ci
301094332d3Sopenharmony_ci    // width
302094332d3Sopenharmony_ci    int16_t width = decInfo.imageHeight & 0xFFFF;
303094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, width);
304094332d3Sopenharmony_ci    if (curPos < 0) {
305094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF width error");
306094332d3Sopenharmony_ci        return curPos;
307094332d3Sopenharmony_ci    }
308094332d3Sopenharmony_ci
309094332d3Sopenharmony_ci    //  height
310094332d3Sopenharmony_ci    int16_t height = decInfo.imageWidth & 0xFFFF;
311094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, height);
312094332d3Sopenharmony_ci    if (curPos < 0) {
313094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF width error");
314094332d3Sopenharmony_ci        return curPos;
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    // components
317094332d3Sopenharmony_ci    int8_t components = decInfo.numComponents & 0xFF;
318094332d3Sopenharmony_ci    curPos = PutInt8(buffer, curPos, components);
319094332d3Sopenharmony_ci    if (curPos < 0) {
320094332d3Sopenharmony_ci        HDF_LOGE("assemble SOF components error");
321094332d3Sopenharmony_ci        return curPos;
322094332d3Sopenharmony_ci    }
323094332d3Sopenharmony_ci    for (size_t i = 0; i < decInfo.compInfo.size(); i++) {
324094332d3Sopenharmony_ci        int8_t componentId = decInfo.compInfo[i].componentId;
325094332d3Sopenharmony_ci        // byte offset
326094332d3Sopenharmony_ci        int8_t sampFactor = ((decInfo.compInfo[i].hSampFactor & 0xFF) << 4) | (decInfo.compInfo[i].vSampFactor & 0xFF);
327094332d3Sopenharmony_ci        int8_t quantity = decInfo.compInfo[i].quantTableNo;
328094332d3Sopenharmony_ci        int8_t bufferValue[] = {componentId, sampFactor, quantity};
329094332d3Sopenharmony_ci        auto ret = memcpy_s(buffer + curPos, sizeof(bufferValue), bufferValue, sizeof(bufferValue));
330094332d3Sopenharmony_ci        if (ret != EOK) {
331094332d3Sopenharmony_ci            HDF_LOGE("assemble component error, ret = %{public}d", ret);
332094332d3Sopenharmony_ci            return ret;
333094332d3Sopenharmony_ci        }
334094332d3Sopenharmony_ci        curPos += sizeof(bufferValue);
335094332d3Sopenharmony_ci    }
336094332d3Sopenharmony_ci    return curPos;
337094332d3Sopenharmony_ci}
338094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegSosAssemble(const struct CodecJpegDecInfo &decInfo, int8_t *buffer, int32_t curPos)
339094332d3Sopenharmony_ci{
340094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
341094332d3Sopenharmony_ci    // flag
342094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, 0xffda);
343094332d3Sopenharmony_ci    if (curPos < 0) {
344094332d3Sopenharmony_ci        HDF_LOGE("assemble SOS flag error");
345094332d3Sopenharmony_ci        return curPos;
346094332d3Sopenharmony_ci    }
347094332d3Sopenharmony_ci
348094332d3Sopenharmony_ci    int16_t len = decInfo.numComponents * 2 + 6; // * rgb table length + other data
349094332d3Sopenharmony_ci    curPos = PutInt16(buffer, curPos, len);
350094332d3Sopenharmony_ci    if (curPos < 0) {
351094332d3Sopenharmony_ci        HDF_LOGE("assemble SOS len error");
352094332d3Sopenharmony_ci        return curPos;
353094332d3Sopenharmony_ci    }
354094332d3Sopenharmony_ci
355094332d3Sopenharmony_ci    int8_t components = decInfo.numComponents & 0xFF;
356094332d3Sopenharmony_ci    curPos = PutInt8(buffer, curPos, components);
357094332d3Sopenharmony_ci    if (curPos < 0) {
358094332d3Sopenharmony_ci        HDF_LOGE("assemble SOS components error");
359094332d3Sopenharmony_ci        return curPos;
360094332d3Sopenharmony_ci    }
361094332d3Sopenharmony_ci
362094332d3Sopenharmony_ci    for (size_t i = 0; i < decInfo.compInfo.size(); i++) {
363094332d3Sopenharmony_ci        int8_t componentId = decInfo.compInfo[i].componentId;
364094332d3Sopenharmony_ci        int8_t indexNo = ((decInfo.compInfo[i].dcTableNo & 0xFF) << 4) | (decInfo.compInfo[i].acTableNo & 0xFF);
365094332d3Sopenharmony_ci        int16_t value = ((componentId << 8) | indexNo) & 0xffff;
366094332d3Sopenharmony_ci        curPos = PutInt16(buffer, curPos, value);
367094332d3Sopenharmony_ci        if (curPos < 0) {
368094332d3Sopenharmony_ci            HDF_LOGE("assemble SOS component value error");
369094332d3Sopenharmony_ci            return curPos;
370094332d3Sopenharmony_ci        }
371094332d3Sopenharmony_ci    }
372094332d3Sopenharmony_ci    int8_t dataStart[] = {0x00, 0x3F, 0x00};
373094332d3Sopenharmony_ci    auto ret = memcpy_s(buffer + curPos, sizeof(dataStart), dataStart, sizeof(dataStart));
374094332d3Sopenharmony_ci    if (ret != EOK) {
375094332d3Sopenharmony_ci        HDF_LOGE("assemble SOS data flag error, ret = %{public}d", ret);
376094332d3Sopenharmony_ci        return ret;
377094332d3Sopenharmony_ci    }
378094332d3Sopenharmony_ci    curPos += sizeof(dataStart);
379094332d3Sopenharmony_ci    return curPos;
380094332d3Sopenharmony_ci}
381094332d3Sopenharmony_ciint32_t CodecJpegHelper::JpegDataAssemble(int8_t *buffer, int32_t curPos, int32_t fd)
382094332d3Sopenharmony_ci{
383094332d3Sopenharmony_ci    HDF_LOGI("enter. curPos = %{public}d", curPos);
384094332d3Sopenharmony_ci    int32_t size = OHOS::AshmemGetSize(fd);
385094332d3Sopenharmony_ci    HDF_LOGI("get size %{public}d from fd %{public}d", size, fd);
386094332d3Sopenharmony_ci    OHOS::Ashmem mem(fd, size);
387094332d3Sopenharmony_ci    // check ret value
388094332d3Sopenharmony_ci    mem.MapReadOnlyAshmem();
389094332d3Sopenharmony_ci    auto addr = const_cast<void *>(mem.ReadFromAshmem(0, 0));
390094332d3Sopenharmony_ci    auto ret = memcpy_s(buffer + curPos, size, addr, size);
391094332d3Sopenharmony_ci    if (ret != EOK) {
392094332d3Sopenharmony_ci        HDF_LOGE("assemble compressed data error, ret = %{public}d", ret);
393094332d3Sopenharmony_ci        mem.UnmapAshmem();
394094332d3Sopenharmony_ci        if (ret > 0) {
395094332d3Sopenharmony_ci            return -ret;
396094332d3Sopenharmony_ci        }
397094332d3Sopenharmony_ci        return ret;
398094332d3Sopenharmony_ci    }
399094332d3Sopenharmony_ci    mem.UnmapAshmem();
400094332d3Sopenharmony_ci    mem.CloseAshmem();
401094332d3Sopenharmony_ci    curPos += size;
402094332d3Sopenharmony_ci    return curPos;
403094332d3Sopenharmony_ci}
404094332d3Sopenharmony_ci
405094332d3Sopenharmony_ciint32_t CodecJpegHelper::DessambleSof(int8_t *buffer, struct CodecJpegDecInfo &decInfo)
406094332d3Sopenharmony_ci{
407094332d3Sopenharmony_ci    HDF_LOGI("dessamble SOI");
408094332d3Sopenharmony_ci    // len
409094332d3Sopenharmony_ci    int32_t len = GetInt16(buffer);
410094332d3Sopenharmony_ci    buffer += 2;  // 2: marker len
411094332d3Sopenharmony_ci    // precision
412094332d3Sopenharmony_ci    decInfo.dataPrecision = GetInt8(buffer);
413094332d3Sopenharmony_ci    buffer++;
414094332d3Sopenharmony_ci    // height
415094332d3Sopenharmony_ci    decInfo.imageHeight = GetInt16(buffer);
416094332d3Sopenharmony_ci    buffer += 2;  // 2: height len
417094332d3Sopenharmony_ci    // width
418094332d3Sopenharmony_ci    decInfo.imageWidth = GetInt16(buffer);
419094332d3Sopenharmony_ci    buffer += 2;  // 2: width len
420094332d3Sopenharmony_ci
421094332d3Sopenharmony_ci    decInfo.numComponents = GetInt8(buffer);
422094332d3Sopenharmony_ci    buffer++;
423094332d3Sopenharmony_ci
424094332d3Sopenharmony_ci    HDF_LOGI("image width[%{public}d],height[%{public}d],components[%{public}d]", decInfo.imageWidth,
425094332d3Sopenharmony_ci        decInfo.imageHeight, decInfo.numComponents);
426094332d3Sopenharmony_ci    for (size_t i = 0; i < decInfo.numComponents; i++) {
427094332d3Sopenharmony_ci        CodecJpegCompInfo comInfo;
428094332d3Sopenharmony_ci
429094332d3Sopenharmony_ci        comInfo.infoFlag = true;
430094332d3Sopenharmony_ci        comInfo.componentId = GetInt8(buffer);
431094332d3Sopenharmony_ci        buffer++;
432094332d3Sopenharmony_ci
433094332d3Sopenharmony_ci        int8_t sampFactor = GetInt8(buffer);
434094332d3Sopenharmony_ci        buffer++;
435094332d3Sopenharmony_ci        comInfo.hSampFactor = (sampFactor >> 4) & 0xFF;  // 4: hsampfactor offset
436094332d3Sopenharmony_ci        comInfo.vSampFactor = sampFactor & 0x0F;
437094332d3Sopenharmony_ci
438094332d3Sopenharmony_ci        comInfo.quantTableNo = GetInt8(buffer);
439094332d3Sopenharmony_ci        buffer++;
440094332d3Sopenharmony_ci        decInfo.compInfo.push_back(std::move(comInfo));
441094332d3Sopenharmony_ci        HDF_LOGI("componentId[%{public}d],hSampFactor[%{public}d],vSampFactor[%{public}d],quantTableNo[%{public}d]",
442094332d3Sopenharmony_ci            comInfo.componentId, comInfo.hSampFactor, comInfo.vSampFactor, comInfo.quantTableNo);
443094332d3Sopenharmony_ci    }
444094332d3Sopenharmony_ci    return len;
445094332d3Sopenharmony_ci}
446094332d3Sopenharmony_ciint32_t CodecJpegHelper::DessambleSos(int8_t *buffer, struct CodecJpegDecInfo &decInfo)
447094332d3Sopenharmony_ci{
448094332d3Sopenharmony_ci    HDF_LOGI("dessamble SOS");
449094332d3Sopenharmony_ci    int32_t len = GetInt16(buffer);
450094332d3Sopenharmony_ci    buffer += 2;  // 2:marker len
451094332d3Sopenharmony_ci
452094332d3Sopenharmony_ci    int32_t components = GetInt8(buffer);
453094332d3Sopenharmony_ci    buffer++;
454094332d3Sopenharmony_ci
455094332d3Sopenharmony_ci    for (int32_t i = 0; i < components; i++) {
456094332d3Sopenharmony_ci        decInfo.compInfo[i].infoFlag = true;
457094332d3Sopenharmony_ci
458094332d3Sopenharmony_ci        int32_t componentId = GetInt8(buffer);
459094332d3Sopenharmony_ci        (void)componentId;
460094332d3Sopenharmony_ci        buffer++;
461094332d3Sopenharmony_ci        // index not used
462094332d3Sopenharmony_ci        auto data = GetInt8(buffer);
463094332d3Sopenharmony_ci        buffer++;
464094332d3Sopenharmony_ci        decInfo.compInfo[i].dcTableNo = (data >> 4) & 0x0F;  // 4: dctable offset
465094332d3Sopenharmony_ci        decInfo.compInfo[i].acTableNo = data & 0x0F;
466094332d3Sopenharmony_ci        HDF_LOGI("componentId[%{public}d],dcTableNo[%{public}d],acTableNo[%{public}d]", componentId,
467094332d3Sopenharmony_ci            decInfo.compInfo[i].dcTableNo, decInfo.compInfo[i].acTableNo);
468094332d3Sopenharmony_ci    }
469094332d3Sopenharmony_ci    buffer += 3;  // skip 0x003F00
470094332d3Sopenharmony_ci    return len;
471094332d3Sopenharmony_ci}
472094332d3Sopenharmony_ciint32_t CodecJpegHelper::DessambleCompressData(int8_t *buffer, std::unique_ptr<int8_t[]> &compressBuffer,
473094332d3Sopenharmony_ci                                               uint32_t &comBufLen)
474094332d3Sopenharmony_ci{
475094332d3Sopenharmony_ci    int8_t *dataStart = buffer;
476094332d3Sopenharmony_ci    do {
477094332d3Sopenharmony_ci        int32_t v = GetInt8(buffer);
478094332d3Sopenharmony_ci        buffer++;
479094332d3Sopenharmony_ci        if (v != 0xff) {
480094332d3Sopenharmony_ci            continue;
481094332d3Sopenharmony_ci        }
482094332d3Sopenharmony_ci        v = GetInt8(buffer);
483094332d3Sopenharmony_ci        buffer++;
484094332d3Sopenharmony_ci        if (v != 0xd9) {
485094332d3Sopenharmony_ci            continue;
486094332d3Sopenharmony_ci        }
487094332d3Sopenharmony_ci        buffer -= 2;  // 2: marker len
488094332d3Sopenharmony_ci        break;
489094332d3Sopenharmony_ci    } while (1);
490094332d3Sopenharmony_ci    comBufLen = (int32_t)(buffer - dataStart) + 1;
491094332d3Sopenharmony_ci    compressBuffer = std::make_unique<int8_t[]>(comBufLen);
492094332d3Sopenharmony_ci    auto ret = memcpy_s(compressBuffer.get(), comBufLen, dataStart, comBufLen);
493094332d3Sopenharmony_ci    if (ret != EOK) {
494094332d3Sopenharmony_ci        HDF_LOGE("copy compressed data error, dataLen %{public}d, ret %{public}d", comBufLen, ret);
495094332d3Sopenharmony_ci        compressBuffer = nullptr;
496094332d3Sopenharmony_ci        return ret;
497094332d3Sopenharmony_ci    }
498094332d3Sopenharmony_ci    return comBufLen;
499094332d3Sopenharmony_ci}
500094332d3Sopenharmony_ciint32_t CodecJpegHelper::DessambleDqt(int8_t *buffer, struct CodecJpegDecInfo &decInfo)
501094332d3Sopenharmony_ci{
502094332d3Sopenharmony_ci    HDF_LOGI("dessamble DQT");
503094332d3Sopenharmony_ci    int8_t *bufferOri = buffer;
504094332d3Sopenharmony_ci    int32_t len = GetInt16(buffer);
505094332d3Sopenharmony_ci    buffer += 2;  // 2: marker len
506094332d3Sopenharmony_ci    // maybe has more dqt table
507094332d3Sopenharmony_ci    while ((buffer - bufferOri) < len) {
508094332d3Sopenharmony_ci        auto data = GetInt8(buffer);
509094332d3Sopenharmony_ci        buffer++;
510094332d3Sopenharmony_ci        int32_t tableId = data & 0x000f;
511094332d3Sopenharmony_ci        (void)tableId;
512094332d3Sopenharmony_ci        int32_t size = 64;
513094332d3Sopenharmony_ci        CodecJpegQuantTable table;
514094332d3Sopenharmony_ci        table.tableFlag = true;
515094332d3Sopenharmony_ci        table.quantVal.resize(size);
516094332d3Sopenharmony_ci        std::vector<uint16_t> mtx;
517094332d3Sopenharmony_ci        HDF_LOGI("tableid[%{public}d]", tableId);
518094332d3Sopenharmony_ci        for (int32_t i = 0; i < size; i++) {
519094332d3Sopenharmony_ci            if (((data >> 4) & 0x0f) == 1) { // 4: low 4 bits, 1: for 16 bits
520094332d3Sopenharmony_ci                mtx.push_back(static_cast<int16_t>(GetInt16(buffer)));
521094332d3Sopenharmony_ci                buffer += 2;  // 2: data offset
522094332d3Sopenharmony_ci            } else {
523094332d3Sopenharmony_ci                mtx.push_back(static_cast<int8_t>(GetInt8(buffer)));
524094332d3Sopenharmony_ci                buffer += 1;  // 1: data offset
525094332d3Sopenharmony_ci            }
526094332d3Sopenharmony_ci        }
527094332d3Sopenharmony_ci        // unzigzag quant table
528094332d3Sopenharmony_ci        for (int32_t i = 0; i < size; i++) {
529094332d3Sopenharmony_ci            table.quantVal[i] = mtx[UnZigZagTable[i]];
530094332d3Sopenharmony_ci        }
531094332d3Sopenharmony_ci        decInfo.quantTbl.push_back(std::move(table));
532094332d3Sopenharmony_ci    }
533094332d3Sopenharmony_ci    return len;
534094332d3Sopenharmony_ci}
535094332d3Sopenharmony_ciint32_t CodecJpegHelper::DessambleDht(int8_t *buffer, struct CodecJpegDecInfo &decInfo)
536094332d3Sopenharmony_ci{
537094332d3Sopenharmony_ci    HDF_LOGI("dessamble DHT");
538094332d3Sopenharmony_ci    int8_t *bufferOri = buffer;
539094332d3Sopenharmony_ci    int32_t len = GetInt16(buffer);
540094332d3Sopenharmony_ci    buffer += 2;  // 2: marker len
541094332d3Sopenharmony_ci    // 可能存在多个表在同一个dht marker 中
542094332d3Sopenharmony_ci    while ((buffer - bufferOri) < len) {
543094332d3Sopenharmony_ci        auto data = GetInt8(buffer);
544094332d3Sopenharmony_ci        buffer++;
545094332d3Sopenharmony_ci        int32_t tableId = data & 0x000f;
546094332d3Sopenharmony_ci        (void)tableId;
547094332d3Sopenharmony_ci        int32_t acOrDc = (data >> 4) & 0x0f;  // 0:DC, 1:AC, 4: ac/dc data offset
548094332d3Sopenharmony_ci        CodecJpegHuffTable table;
549094332d3Sopenharmony_ci        table.tableFlag = true;
550094332d3Sopenharmony_ci        int32_t num = 0;
551094332d3Sopenharmony_ci        for (size_t i = 0; i < 16; i++) {  // 16: Data size
552094332d3Sopenharmony_ci            auto data = GetInt8(buffer);
553094332d3Sopenharmony_ci            buffer++;
554094332d3Sopenharmony_ci            table.bits.push_back(data);
555094332d3Sopenharmony_ci            num += data & 0x00ff;
556094332d3Sopenharmony_ci        }
557094332d3Sopenharmony_ci        HDF_LOGI("tableid[%{public}d], acOrDc[%{public}d], num[%{public}d]", tableId, acOrDc, num);
558094332d3Sopenharmony_ci        // val
559094332d3Sopenharmony_ci        for (int32_t i = 0; i < num; i++) {
560094332d3Sopenharmony_ci            table.huffVal.push_back(*buffer++);
561094332d3Sopenharmony_ci        }
562094332d3Sopenharmony_ci        if (acOrDc == 1) {
563094332d3Sopenharmony_ci            decInfo.acHuffTbl.push_back(std::move(table));
564094332d3Sopenharmony_ci        } else {
565094332d3Sopenharmony_ci            decInfo.dcHuffTbl.push_back(std::move(table));
566094332d3Sopenharmony_ci        }
567094332d3Sopenharmony_ci    }
568094332d3Sopenharmony_ci    return len;
569094332d3Sopenharmony_ci}
570094332d3Sopenharmony_ci
571094332d3Sopenharmony_ciint32_t CodecJpegHelper::FindMarker(int8_t *start)
572094332d3Sopenharmony_ci{
573094332d3Sopenharmony_ci    int32_t marker = GetInt16(start);
574094332d3Sopenharmony_ci    return marker;
575094332d3Sopenharmony_ci}
576094332d3Sopenharmony_ci
577094332d3Sopenharmony_ciint32_t CodecJpegHelper::PutInt16(int8_t *buffer, int32_t curPos, int16_t value)
578094332d3Sopenharmony_ci{
579094332d3Sopenharmony_ci    int8_t data[] = {value >> 8, value & 0xFF};
580094332d3Sopenharmony_ci    auto ret = memcpy_s(buffer + curPos, sizeof(data), data, sizeof(data));
581094332d3Sopenharmony_ci    if (ret != EOK) {
582094332d3Sopenharmony_ci        HDF_LOGE("memcpy ret err %{public}d", ret);
583094332d3Sopenharmony_ci        return -1;
584094332d3Sopenharmony_ci    }
585094332d3Sopenharmony_ci    return curPos + sizeof(data);
586094332d3Sopenharmony_ci}
587094332d3Sopenharmony_ci
588094332d3Sopenharmony_ciint32_t CodecJpegHelper::PutInt8(int8_t *buffer, int32_t curPos, int8_t value)
589094332d3Sopenharmony_ci{
590094332d3Sopenharmony_ci    auto ret = memcpy_s(buffer + curPos, sizeof(value), &value, sizeof(value));
591094332d3Sopenharmony_ci    if (ret != EOK) {
592094332d3Sopenharmony_ci        HDF_LOGE("memcpy ret err %{public}d", ret);
593094332d3Sopenharmony_ci        return -1;
594094332d3Sopenharmony_ci    }
595094332d3Sopenharmony_ci    return curPos + sizeof(value);
596094332d3Sopenharmony_ci}
597094332d3Sopenharmony_ci
598094332d3Sopenharmony_ciint32_t CodecJpegHelper::GetInt8(int8_t *buffer)
599094332d3Sopenharmony_ci{
600094332d3Sopenharmony_ci    return buffer[0] & 0x00ff;
601094332d3Sopenharmony_ci}
602094332d3Sopenharmony_ci
603094332d3Sopenharmony_ciint32_t CodecJpegHelper::GetInt16(int8_t *buffer)
604094332d3Sopenharmony_ci{
605094332d3Sopenharmony_ci    return ((buffer[0] << 8) & 0x00ff00) | (buffer[1] & 0x00ff);  // 8:data offset
606094332d3Sopenharmony_ci}
607