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