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