• 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 <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