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 <sys/mman.h>
22 #include "codec_log_wrapper.h"
23 #include "jpeg_decoder.h"
24
25 using namespace OHOS::HDI::Codec::Image::V2_1;
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 CODEC_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 CODEC_LOGI("----------------- Image capability [%{public}d] -------------------", index + 1);
73 CODEC_LOGI("name:[%{public}s]", cap.name.c_str());
74 CODEC_LOGI("role:[%{public}d]", cap.role);
75 CODEC_LOGI("type:[%{public}d]", cap.type);
76 CODEC_LOGI("maxSample:[%{public}d]", cap.maxSample);
77 CODEC_LOGI("maxWidth:[%{public}d]", cap.maxWidth);
78 CODEC_LOGI("maxHeight:[%{public}d]", cap.maxHeight);
79 CODEC_LOGI("minWidth:[%{public}d]", cap.minWidth);
80 CODEC_LOGI("minHeight:[%{public}d]", cap.minHeight);
81 CODEC_LOGI("maxInst:[%{public}d]", cap.maxInst);
82 CODEC_LOGI("isSoftwareCodec:[%{public}d]", cap.isSoftwareCodec);
83 CODEC_LOGI("supportPixFmts:%{public}s", GetArrayStr(cap.supportPixFmts, arrayStr).c_str());
84 CODEC_LOGI("-------------------------------------------------------------------");
85 }
86
Init()87 int32_t JpegDecoder::Init()
88 {
89 if (hdiJpeg_ == nullptr || hdiBuffer_ == nullptr) {
90 CODEC_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 CODEC_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 CODEC_LOGI("enter callback , ret [%{public}d] !", error);
116 if (error != HDF_SUCCESS) {
117 CODEC_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 CODEC_LOGI("decode and write output buffer succ !");
129
130 // freeInBuffer
131 auto ret = hdiJpeg_->FreeInBuffer(inBuffer_);
132 if (ret != HDF_SUCCESS) {
133 CODEC_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 CODEC_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 CODEC_LOGI("bufferLen_ is [%{public}d]!", bufferLen_);
150 jpegBuffer_ = std::make_unique<char[]>(bufferLen_);
151 if (jpegBuffer_ == nullptr) {
152 CODEC_LOGE("make_unique jpegBuffer_ failed !");
153 return HDF_FAILURE;
154 }
155 ioIn_.read(jpegBuffer_.get(), bufferLen_);
156
157 CODEC_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 CODEC_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_, compDataLen_, CODEC_IMAGE_JPEG);
171 if (ret != HDF_SUCCESS) {
172 CODEC_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_YCRCB_420_SP};
180
181 BufferHandle *handle = nullptr;
182 ret = hdiBuffer_->AllocMem(alloc, handle);
183 if (ret != HDF_SUCCESS) {
184 CODEC_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 CODEC_LOGI("write jpeg data to inBuffer !");
206 BufferHandle *bufferHandle = inBuffer_.buffer->GetBufferHandle();
207 bufferHandle->virAddr = mmap(nullptr, bufferHandle->size, PROT_READ | PROT_WRITE,
208 MAP_SHARED, bufferHandle->fd, 0);
209 if (bufferHandle->virAddr == MAP_FAILED) {
210 CODEC_LOGE("failed to map input buffer");
211 return false;
212 }
213 auto res = memcpy_s(bufferHandle->virAddr, compDataLen_, compressBuffer_.get(), compDataLen_);
214 if (res != 0) {
215 CODEC_LOGE("memcpy_s failed, err [%{public}d] !", res);
216 return HDF_FAILURE;
217 }
218 munmap(bufferHandle->virAddr, bufferHandle->size);
219
220 CODEC_LOGI("start jpeg decoding !");
221 decInfo_.sampleSize = 1;
222 decInfo_.compressPos = 0;
223 ret = hdiJpeg_->DoJpegDecode(inBuffer_, outBuffer_, decInfo_);
224 if (ret != HDF_SUCCESS) {
225 CODEC_LOGE("DoJpegDecode failed, err [%{public}d] !", ret);
226 return HDF_FAILURE;
227 }
228
229 // write decode result
230 BufferHandle *outHandle = outBuffer_.buffer->Move();
231 hdiBuffer_->Mmap(*outHandle);
232 ioOut_.write(reinterpret_cast<char *>(outHandle->virAddr), outHandle->size);
233 ioOut_.flush();
234 hdiBuffer_->Unmap(*outHandle);
235 hdiBuffer_->FreeMem(*outHandle);
236 CODEC_LOGI("decode and write output buffer succ !");
237
238 // freeInBuffer
239 ret = hdiJpeg_->FreeInBuffer(inBuffer_);
240 if (ret != HDF_SUCCESS) {
241 CODEC_LOGE("FreeInBuffer failed, err [%{public}d] !", ret);
242 }
243 return HDF_SUCCESS;
244 }
245
main(int argc,char * argv[])246 int main(int argc, char *argv[])
247 {
248 CommandOpt opt;
249 CommandParse parse;
250 if (!parse.Parse(argc, argv, opt)) {
251 return HDF_FAILURE;
252 }
253 decoder = std::make_shared<JpegDecoder>();
254 auto ret = decoder->Init();
255 if (ret != HDF_SUCCESS) {
256 (void)decoder->DeInit();
257 decoder = nullptr;
258 return HDF_FAILURE;
259 }
260
261 ret = decoder->Decode(opt);
262 if (ret != HDF_SUCCESS) {
263 (void)decoder->DeInit();
264 decoder = nullptr;
265 return HDF_FAILURE;
266 }
267
268 ret = decoder->DeInit();
269 if (ret != HDF_SUCCESS) {
270 CODEC_LOGE("DeInit failed, err [%{public}d] !", ret);
271 }
272 decoder = nullptr;
273 return 0;
274 }
275