1 /*
2  * Copyright (c) 2023 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 #include <ashmem.h>
16 #include <dlfcn.h>
17 #include <osal_mem.h>
18 #include <securec.h>
19 #include <cstdio>
20 #include <unistd.h>
21 #include "hdf_log.h"
22 #include "jpeg_decoder.h"
23 #define HDF_LOG_TAG codec_jpeg_decoder
24 
25 using namespace OHOS::HDI::Codec::Image::V2_0;
26 using namespace OHOS::HDI::Display::Buffer::V1_0;
27 using namespace OHOS::HDI::Display::Composer::V1_0;
28 
29 static std::shared_ptr<JpegDecoder> decoder;
JpegDecoder()30 JpegDecoder::JpegDecoder()
31 {
32     hdiJpeg_ = ICodecImage::Get();
33     hdiBuffer_ = IDisplayBuffer::Get();
34     helper_ = new CodecJpegHelper();
35 }
36 
~JpegDecoder()37 JpegDecoder::~JpegDecoder()
38 {
39     hdiJpeg_ = nullptr;
40     hdiBuffer_ = nullptr;
41     if (helper_ != nullptr) {
42         delete helper_;
43         helper_ = nullptr;
44     }
45     if (ioOut_.is_open()) {
46         ioOut_.close();
47     }
48     if (ioIn_.is_open()) {
49         ioIn_.close();
50     }
51 }
52 
GetArrayStr(const std::vector<uint32_t> & vec,std::string & arrayStr)53 static std::string GetArrayStr(const std::vector<uint32_t> &vec, std::string &arrayStr)
54 {
55     arrayStr = ("[");
56     for (size_t i = 0; i < vec.size(); i++) {
57         char value[32] = {0};
58         int ret = sprintf_s(value, sizeof(value) - 1, "0x0%X, ", vec[i]);
59         if (ret < 0) {
60             HDF_LOGE("sprintf_s value failed, error [%{public}d]", ret);
61             break;
62         }
63         arrayStr += value;
64     }
65     arrayStr += "]";
66     return arrayStr;
67 }
68 
PrintCapability(const CodecImageCapability & cap,int32_t index)69 static void PrintCapability(const CodecImageCapability &cap, int32_t index)
70 {
71     std::string arrayStr("");
72     HDF_LOGI("----------------- Image capability [%{public}d] -------------------", index + 1);
73     HDF_LOGI("name:[%{public}s]", cap.name.c_str());
74     HDF_LOGI("role:[%{public}d]", cap.role);
75     HDF_LOGI("type:[%{public}d]", cap.type);
76     HDF_LOGI("maxSample:[%{public}d]", cap.maxSample);
77     HDF_LOGI("maxWidth:[%{public}d]", cap.maxWidth);
78     HDF_LOGI("maxHeight:[%{public}d]", cap.maxHeight);
79     HDF_LOGI("minWidth:[%{public}d]", cap.minWidth);
80     HDF_LOGI("minHeight:[%{public}d]", cap.minHeight);
81     HDF_LOGI("maxInst:[%{public}d]", cap.maxInst);
82     HDF_LOGI("isSoftwareCodec:[%{public}d]", cap.isSoftwareCodec);
83     HDF_LOGI("supportPixFmts:%{public}s", GetArrayStr(cap.supportPixFmts, arrayStr).c_str());
84     HDF_LOGI("-------------------------------------------------------------------");
85 }
86 
Init()87 int32_t JpegDecoder::Init()
88 {
89     if (hdiJpeg_ == nullptr || hdiBuffer_ == nullptr) {
90         HDF_LOGE("hdiJpeg_ or hdiBuffer_ is null !");
91         return HDF_FAILURE;
92     }
93     std::vector<CodecImageCapability> capList;
94     auto ret = hdiJpeg_->GetImageCapability(capList);
95     if (ret != HDF_SUCCESS) {
96         HDF_LOGE("GetImageCapability failed, err [%{public}d] !", ret);
97         return HDF_FAILURE;
98     }
99     for (size_t i = 0; i < capList.size(); i++) {
100         PrintCapability(capList[i], i);
101     }
102     return hdiJpeg_->Init(CODEC_IMAGE_JPEG);
103 }
104 
DeInit()105 int32_t JpegDecoder::DeInit()
106 {
107     if (hdiJpeg_ == nullptr) {
108         return HDF_FAILURE;
109     }
110     return hdiJpeg_->DeInit(CODEC_IMAGE_JPEG);
111 }
112 
OnEvent(int32_t error)113 int32_t JpegDecoder::OnEvent(int32_t error)
114 {
115     HDF_LOGI("enter callback , ret [%{public}d] !", error);
116     if (error != HDF_SUCCESS) {
117         HDF_LOGE("hardware decode error, should to decode by software !");
118     }
119     // write decode result
120     if (error == HDF_SUCCESS) {
121         BufferHandle *outHandle = outBuffer_.buffer->GetBufferHandle();
122         hdiBuffer_->Mmap(*outHandle);
123         ioOut_.write(reinterpret_cast<char *>(outHandle->virAddr), outHandle->size);
124         ioOut_.flush();
125         hdiBuffer_->Unmap(*outHandle);
126         hdiBuffer_->FreeMem(*outHandle);
127     }
128     HDF_LOGI("decode and write output buffer succ !");
129 
130     // freeInBuffer
131     auto ret = hdiJpeg_->FreeInBuffer(inBuffer_);
132     if (ret != HDF_SUCCESS) {
133         HDF_LOGE("FreeInBuffer failed, err [%{public}d] !", ret);
134     }
135     return ret;
136 }
137 
PrepareData(std::string fileInput,std::string fileOutput)138 int32_t JpegDecoder::PrepareData(std::string fileInput, std::string fileOutput)
139 {
140     HDF_LOGI("start read jpeg image data !");
141 
142     ioIn_.open(fileInput, std::ios_base::binary);
143     ioOut_.open(fileOutput, std::ios_base::binary | std::ios_base::trunc);
144 
145     ioIn_.seekg(0, ioIn_.end);
146     bufferLen_ = ioIn_.tellg();
147     ioIn_.seekg(0, ioIn_.beg);
148 
149     HDF_LOGE("bufferLen_ is [%{public}d]!", bufferLen_);
150     jpegBuffer_ = std::make_unique<char[]>(bufferLen_);
151     if (jpegBuffer_ == nullptr) {
152         HDF_LOGE("make_unique jpegBuffer_ failed !");
153         return HDF_FAILURE;
154     }
155     ioIn_.read(jpegBuffer_.get(), bufferLen_);
156 
157     HDF_LOGI("start parse jpeg header data !");
158     bool err = helper_->DessambleJpeg(reinterpret_cast<int8_t *>(jpegBuffer_.get()), bufferLen_,
159         decInfo_, compressBuffer_, compDataLen_, dataStart_);
160     if (!err) {
161         HDF_LOGE("DecodeJpegHeader failed !");
162         return HDF_FAILURE;
163     }
164     return HDF_SUCCESS;
165 }
166 
AllocBuffer(uint32_t width,uint32_t height)167 int32_t JpegDecoder::AllocBuffer(uint32_t width, uint32_t height)
168 {
169     // alloc inBuffer
170     auto ret = hdiJpeg_->AllocateInBuffer(inBuffer_, bufferLen_, CODEC_IMAGE_JPEG);
171     if (ret != HDF_SUCCESS) {
172         HDF_LOGE("AllocateInBuffer failed, err [%{public}d] !", ret);
173         return HDF_FAILURE;
174     }
175     // alloc outBuffer
176     AllocInfo alloc = {.width = AlignUp(width),
177                        .height = height,
178                        .usage =  HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
179                        .format = PIXEL_FMT_YCBCR_420_SP};
180 
181     BufferHandle *handle = nullptr;
182     ret = hdiBuffer_->AllocMem(alloc, handle);
183     if (ret != HDF_SUCCESS) {
184         HDF_LOGE("AllocMem failed, err [%{public}d] !", ret);
185         return HDF_FAILURE;
186     }
187 
188     outBuffer_.buffer = new NativeBuffer(handle);
189     outBuffer_.fenceFd = -1;
190     return HDF_SUCCESS;
191 }
192 
Decode(CommandOpt opt)193 int32_t JpegDecoder::Decode(CommandOpt opt)
194 {
195     auto ret = PrepareData(opt.fileInput, opt.fileOutput);
196     if (ret != HDF_SUCCESS) {
197         return HDF_FAILURE;
198     }
199 
200     ret = decoder->AllocBuffer(opt.width, opt.height);
201     if (ret != HDF_SUCCESS) {
202         return HDF_FAILURE;
203     }
204 
205     HDF_LOGI("write jpeg data to inBuffer !");
206     BufferHandle *bufferHandle = inBuffer_.buffer->GetBufferHandle();
207     hdiBuffer_->Mmap(*bufferHandle);
208     auto res  = memcpy_s(bufferHandle->virAddr, bufferLen_, jpegBuffer_.get(), bufferLen_);
209     if (res != 0) {
210         HDF_LOGE("memcpy_s failed, err [%{public}d] !", res);
211         return HDF_FAILURE;
212     }
213     hdiBuffer_->Unmap(*bufferHandle);
214 
215     HDF_LOGI("start jpeg decoding !");
216     decInfo_.sampleSize = 1;
217     decInfo_.compressPos = dataStart_;
218     ret = hdiJpeg_->DoJpegDecode(inBuffer_, outBuffer_, decInfo_);
219     if (ret != HDF_SUCCESS) {
220         HDF_LOGE("DoJpegDecode failed, err [%{public}d] !", ret);
221         return HDF_FAILURE;
222     }
223 
224     // write decode result
225     BufferHandle *outHandle = outBuffer_.buffer->Move();
226     hdiBuffer_->Mmap(*outHandle);
227     ioOut_.write(reinterpret_cast<char *>(outHandle->virAddr), outHandle->size);
228     ioOut_.flush();
229     hdiBuffer_->Unmap(*outHandle);
230     hdiBuffer_->FreeMem(*outHandle);
231     HDF_LOGI("decode and write output buffer succ !");
232 
233     // freeInBuffer
234     ret = hdiJpeg_->FreeInBuffer(inBuffer_);
235     if (ret != HDF_SUCCESS) {
236         HDF_LOGE("FreeInBuffer failed, err [%{public}d] !", ret);
237     }
238     return HDF_SUCCESS;
239 }
240 
main(int argc,char * argv[])241 int main(int argc, char *argv[])
242 {
243     CommandOpt opt;
244     CommandParse parse;
245     if (!parse.Parse(argc, argv, opt)) {
246         return HDF_FAILURE;
247     }
248     decoder = std::make_shared<JpegDecoder>();
249     auto ret = decoder->Init();
250     if (ret != HDF_SUCCESS) {
251         (void)decoder->DeInit();
252         decoder = nullptr;
253         return HDF_FAILURE;
254     }
255 
256     ret = decoder->Decode(opt);
257     if (ret != HDF_SUCCESS) {
258         (void)decoder->DeInit();
259         decoder = nullptr;
260         return HDF_FAILURE;
261     }
262 
263     ret = decoder->DeInit();
264     if (ret != HDF_SUCCESS) {
265         HDF_LOGE("DeInit failed, err [%{public}d] !", ret);
266     }
267     decoder = nullptr;
268     return 0;
269 }
270