• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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