• 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 applicable 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 
16 #include "hardware/jpeg_hw_decoder.h"
17 
18 #include <vector>
19 #include <algorithm>
20 #include <chrono>
21 #include <securec.h>
22 #include <sys/mman.h>
23 
24 #include "hardware/jpeg_marker_define.h"
25 #include "hardware/jpeg_dma_pool.h"
26 #include "hdf_base.h"
27 #include "iremote_object.h"
28 #include "iproxy_broker.h"
29 #include "media_errors.h"
30 #include "image_trace.h"
31 #include "src/codec/SkJpegUtility.h"
32 #include "src/codec/SkJpegDecoderMgr.h"
33 #include "src/codec/SkJpegCodec.h"
34 
35 namespace OHOS::ImagePlugin {
36 using namespace OHOS::HDI::Codec::Image::V2_1;
37 using namespace Media;
38 
39 static std::mutex g_codecMtx;
40 static sptr<ICodecImage> g_codecMgr;
41 std::vector<CodecImageCapability> JpegHardwareDecoder::capList_ = {};
42 std::mutex JpegHardwareDecoder::capListMtx_;
43 
44 class CodecJpegDeathRecipient : public IRemoteObject::DeathRecipient {
45 public:
OnRemoteDied(const wptr<IRemoteObject> & object)46     void OnRemoteDied(const wptr<IRemoteObject> &object) override
47     {
48         JPEG_HW_LOGW("codec_image_service died");
49         std::lock_guard<std::mutex> lk(g_codecMtx);
50         g_codecMgr = nullptr;
51     }
52 };
53 
GetCodecManager()54 static sptr<ICodecImage> GetCodecManager()
55 {
56     std::lock_guard<std::mutex> lk(g_codecMtx);
57     if (g_codecMgr) {
58         return g_codecMgr;
59     }
60     JPEG_HW_LOGI("need to get ICodecImage");
61     g_codecMgr = ICodecImage::Get();
62     if (g_codecMgr == nullptr) {
63         return nullptr;
64     }
65     bool isDeathRecipientAdded = false;
66     const sptr<OHOS::IRemoteObject> &remote = OHOS::HDI::hdi_objcast<ICodecImage>(g_codecMgr);
67     if (remote) {
68         sptr<CodecJpegDeathRecipient> deathCallBack(new CodecJpegDeathRecipient());
69         isDeathRecipientAdded = remote->AddDeathRecipient(deathCallBack);
70     }
71     if (!isDeathRecipientAdded) {
72         JPEG_HW_LOGE("failed to add deathRecipient for ICodecImage!");
73     }
74     return g_codecMgr;
75 }
76 
LifeSpanTimer(std::string desc)77 JpegHardwareDecoder::LifeSpanTimer::LifeSpanTimer(std::string desc) : desc_(desc)
78 {
79     startTimeInUs_ = GetCurrentTimeInUs();
80 }
81 
~LifeSpanTimer()82 JpegHardwareDecoder::LifeSpanTimer::~LifeSpanTimer()
83 {
84     static constexpr float MILLISEC_TO_MICROSEC = 1000.0f;
85     int64_t timeSpanInUs = GetCurrentTimeInUs() - startTimeInUs_;
86     JPEG_HW_LOGD("%{public}s cost: %{public}.2f ms",
87                  desc_.c_str(), static_cast<float>(timeSpanInUs / MILLISEC_TO_MICROSEC));
88 }
89 
GetCurrentTimeInUs()90 int64_t JpegHardwareDecoder::LifeSpanTimer::GetCurrentTimeInUs()
91 {
92     auto now = std::chrono::steady_clock::now();
93     return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
94 }
95 
JpegHardwareDecoder()96 JpegHardwareDecoder::JpegHardwareDecoder()
97 {
98     inputBuffer_.fenceFd = -1;
99     hwDecoder_ = GetCodecManager();
100 }
101 
~JpegHardwareDecoder()102 JpegHardwareDecoder::~JpegHardwareDecoder()
103 {
104     hwDecoder_ = nullptr;
105 }
106 
IsHardwareDecodeSupported(const std::string & srcImgFormat,OHOS::Media::Size srcImgSize)107 bool JpegHardwareDecoder::IsHardwareDecodeSupported(const std::string& srcImgFormat, OHOS::Media::Size srcImgSize)
108 {
109     if (hwDecoder_ == nullptr) {
110         JPEG_HW_LOGE("failed to get hardware decoder!");
111         return false;
112     }
113     if (srcImgFormat != JPEG_FORMAT_DESC) {
114         JPEG_HW_LOGE("invalid image format: %{public}s", srcImgFormat.c_str());
115         return false;
116     }
117     std::lock_guard<std::mutex> lock(capListMtx_);
118     if (capList_.size() == 0) {
119         auto ret = hwDecoder_->GetImageCapability(capList_);
120         if (ret != HDF_SUCCESS) {
121             JPEG_HW_LOGE("failed to get image capability, err=%{public}d!", ret);
122             return false;
123         }
124     }
125 
126     for (const CodecImageCapability& cap : capList_) {
127         JPEG_HW_LOGD("cap info: isSoftwareCodec=%{public}d, role=%{public}d, type=%{public}d, " \
128                      "maxSize=[%{public}u*%{public}u], minSize=[%{public}u*%{public}u]",
129                      cap.isSoftwareCodec, cap.role, cap.type, cap.maxWidth, cap.maxHeight,
130                      cap.minWidth, cap.minHeight);
131         if (!cap.isSoftwareCodec && cap.role == CODEC_IMAGE_JPEG &&
132             cap.type == CODEC_IMAGE_TYPE_DECODER &&
133             srcImgSize.width >= static_cast<int32_t>(cap.minWidth) &&
134             srcImgSize.width <= static_cast<int32_t>(cap.maxWidth) &&
135             srcImgSize.height >= static_cast<int32_t>(cap.minHeight) &&
136             srcImgSize.height <= static_cast<int32_t>(cap.maxHeight)) {
137             JPEG_HW_LOGD("decoder(%{public}s) selected", cap.name.c_str());
138             return true;
139         }
140     }
141     JPEG_HW_LOGE("no available hardware decoder, img=[%{public}ux%{public}u]", srcImgSize.width, srcImgSize.height);
142     return false;
143 }
144 
GetJpegCompressInfo(SkCodec * codec)145 static jpeg_decompress_struct* GetJpegCompressInfo(SkCodec *codec)
146 {
147     if (codec == nullptr) {
148         JPEG_HW_LOGE("invalid input codec!");
149         return nullptr;
150     }
151     SkJpegCodec* jpegCodec = static_cast<SkJpegCodec*>(codec);
152     if (jpegCodec == nullptr) {
153         JPEG_HW_LOGE("invalid input jpeg codec!");
154         return nullptr;
155     }
156     if (jpegCodec->decoderMgr() == nullptr) {
157         JPEG_HW_LOGE("invalid input jpeg codec mgr!");
158         return nullptr;
159     }
160     return jpegCodec->decoderMgr()->dinfo();
161 }
162 
CheckInputColorFmt(SkCodec * codec)163 bool JpegHardwareDecoder::CheckInputColorFmt(SkCodec *codec)
164 {
165     jpeg_decompress_struct* jpegCompressInfo = GetJpegCompressInfo(codec);
166     if (jpegCompressInfo == nullptr) {
167         JPEG_HW_LOGE("failed to get jpeg info");
168         return false;
169     }
170     if (jpegCompressInfo->jpeg_color_space != JCS_YCbCr) {
171         JPEG_HW_LOGI("unsupported in color: %{public}d", jpegCompressInfo->jpeg_color_space);
172         return false;
173     }
174     return true;
175 }
176 
Decode(SkCodec * codec,ImagePlugin::InputDataStream * srcStream,OHOS::Media::Size srcImgSize,uint32_t sampleSize,CodecImageBuffer & outputBuffer)177 uint32_t JpegHardwareDecoder::Decode(SkCodec *codec, ImagePlugin::InputDataStream *srcStream,
178                                      OHOS::Media::Size srcImgSize, uint32_t sampleSize, CodecImageBuffer& outputBuffer)
179 {
180     Media::ImageTrace imageTrace("JpegHardwareDecoder::Decode");
181     LifeSpanTimer decodeTimer("jpeg hardware decode");
182     JPEG_HW_LOGD("img=[%{public}ux%{public}u], sampleSize=%{public}u",
183                  srcImgSize.width, srcImgSize.height, sampleSize);
184     if (hwDecoder_ == nullptr) {
185         JPEG_HW_LOGE("failed to get hardware decoder!");
186         return Media::ERR_IMAGE_DECODE_ABNORMAL;
187     }
188     if (!IsHardwareDecodeSupported(JPEG_FORMAT_DESC, srcImgSize) || !CheckInputColorFmt(codec)) {
189         return Media::ERR_IMAGE_DATA_UNSUPPORT;
190     }
191 
192     decodeInfo_.sampleSize = sampleSize;
193     bool ret = true;
194     ret = ret && PrepareInputData(codec, srcStream);
195     ret = ret && DoDecode(outputBuffer);
196     RecycleAllocatedResource();
197     if (ret) {
198         JPEG_HW_LOGD("jpeg hardware decode succeed");
199         return Media::SUCCESS;
200     }
201     return Media::ERR_IMAGE_DECODE_FAILED;
202 }
203 
AssembleComponentInfo(jpeg_decompress_struct * jpegCompressInfo)204 bool JpegHardwareDecoder::AssembleComponentInfo(jpeg_decompress_struct* jpegCompressInfo)
205 {
206     static constexpr int ONE_COMPONENT = 1;
207     static constexpr int THREE_COMPONENTS = 3;
208     if (jpegCompressInfo->num_components != ONE_COMPONENT &&
209         jpegCompressInfo->num_components != THREE_COMPONENTS) {
210         JPEG_HW_LOGE("unsupported component number: %{public}d!", jpegCompressInfo->num_components);
211         return false;
212     }
213     decodeInfo_.numComponents = static_cast<uint32_t>(jpegCompressInfo->num_components);
214     for (int i = 0; i < jpegCompressInfo->num_components; ++i) {
215         decodeInfo_.compInfo.emplace_back(CodecJpegCompInfo {
216             .componentId = jpegCompressInfo->comp_info[i].component_id,
217             .componentIndex = jpegCompressInfo->comp_info[i].component_index,
218             .hSampFactor = jpegCompressInfo->comp_info[i].h_samp_factor,
219             .vSampFactor = jpegCompressInfo->comp_info[i].v_samp_factor,
220             .quantTableNo = jpegCompressInfo->comp_info[i].quant_tbl_no,
221             .dcTableNo = jpegCompressInfo->comp_info[i].dc_tbl_no,
222             .acTableNo = jpegCompressInfo->comp_info[i].ac_tbl_no,
223             .infoFlag = true
224         });
225     }
226     return true;
227 }
228 
HuffmanTblTransform(JHUFF_TBL * huffTbl,CodecJpegHuffTable & tbl)229 bool JpegHardwareDecoder::HuffmanTblTransform(JHUFF_TBL* huffTbl, CodecJpegHuffTable& tbl)
230 {
231     if (huffTbl == nullptr) {
232         return false;
233     }
234     // length of bits is defined as 16 in jpeg specification
235     // bits defined in struct JHUFF_TBL has length of 17, bits[0] is unused
236     static constexpr int LIST_BITS_OFFSET = 1;
237     static constexpr int LIST_BITS_LEN = 16;
238     static constexpr int MAX_LIST_HUFFVAL_LEN = 256;
239     int actualHuffValLen = 0;
240     for (int i = LIST_BITS_OFFSET; i <= LIST_BITS_LEN; ++i) {
241         actualHuffValLen += huffTbl->bits[i];
242     }
243     JPEG_HW_LOGD("actualHuffValLen=%{public}d", actualHuffValLen);
244     if (actualHuffValLen >= MAX_LIST_HUFFVAL_LEN) {
245         JPEG_HW_LOGE("invalid huffVal len: %{public}d", actualHuffValLen);
246         return false;
247     }
248     tbl.tableFlag = true;
249     tbl.bits = std::vector<uint8_t>(&huffTbl->bits[LIST_BITS_OFFSET],
250                                     &huffTbl->bits[LIST_BITS_OFFSET] + LIST_BITS_LEN);
251     tbl.huffVal = std::vector<uint8_t>(huffTbl->huffval, &huffTbl->huffval[actualHuffValLen]);
252     return true;
253 }
254 
AssembleHuffmanTable(jpeg_decompress_struct * jpegCompressInfo)255 void JpegHardwareDecoder::AssembleHuffmanTable(jpeg_decompress_struct* jpegCompressInfo)
256 {
257     static constexpr int HUFFMAN_TBL_CNT = 4;
258     for (int i = 0; i < HUFFMAN_TBL_CNT; ++i) {
259         CodecJpegHuffTable dcTbl;
260         if (HuffmanTblTransform(jpegCompressInfo->dc_huff_tbl_ptrs[i], dcTbl)) {
261             decodeInfo_.dcHuffTbl.emplace_back(dcTbl);
262         }
263 
264         CodecJpegHuffTable acTbl;
265         if (HuffmanTblTransform(jpegCompressInfo->ac_huff_tbl_ptrs[i], acTbl)) {
266             decodeInfo_.acHuffTbl.emplace_back(acTbl);
267         }
268     }
269 }
270 
AssembleQuantizationTable(jpeg_decompress_struct * jpegCompressInfo)271 void JpegHardwareDecoder::AssembleQuantizationTable(jpeg_decompress_struct* jpegCompressInfo)
272 {
273     for (int i = 0; i < NUM_QUANT_TBLS; ++i) {
274         if (jpegCompressInfo->quant_tbl_ptrs[i]) {
275             uint16_t* quantStart = reinterpret_cast<uint16_t *>(jpegCompressInfo->quant_tbl_ptrs[i]->quantval);
276             decodeInfo_.quantTbl.emplace_back(CodecJpegQuantTable {
277                 .quantVal = std::vector<uint16_t>(quantStart, quantStart + DCTSIZE2),
278                 .tableFlag = true
279             });
280         } else {
281             decodeInfo_.quantTbl.emplace_back(CodecJpegQuantTable {
282                 .quantVal = {},
283                 .tableFlag = false
284             });
285         }
286     }
287 }
288 
AssembleJpegImgHeader(jpeg_decompress_struct * jpegCompressInfo)289 bool JpegHardwareDecoder::AssembleJpegImgHeader(jpeg_decompress_struct* jpegCompressInfo)
290 {
291     decodeInfo_.imageWidth = jpegCompressInfo->image_width;
292     decodeInfo_.imageHeight = jpegCompressInfo->image_height;
293     decodeInfo_.dataPrecision = static_cast<uint32_t>(jpegCompressInfo->data_precision);
294     decodeInfo_.restartInterval = jpegCompressInfo->restart_interval;
295     decodeInfo_.arithCode = jpegCompressInfo->arith_code;
296     decodeInfo_.progressiveMode = jpegCompressInfo->progressive_mode;
297     // no crop as default
298     decodeInfo_.region.flag = 0;
299     if (!AssembleComponentInfo(jpegCompressInfo)) {
300         return false;
301     }
302     AssembleHuffmanTable(jpegCompressInfo);
303     AssembleQuantizationTable(jpegCompressInfo);
304     return true;
305 }
306 
CopySrcToInputBuff(ImagePlugin::InputDataStream * srcStream,BufferHandle * inputBufferHandle)307 bool JpegHardwareDecoder::CopySrcToInputBuff(ImagePlugin::InputDataStream* srcStream, BufferHandle* inputBufferHandle)
308 {
309     uint32_t positionRecord = srcStream->Tell();
310     srcStream->Seek(compressDataPos_);
311     uint32_t readSize = 0;
312     bool flag = srcStream->Read(compressDataSize_,
313                                 static_cast<uint8_t *>(inputBufferHandle->virAddr),
314                                 static_cast<uint32_t>(inputBufferHandle->size),
315                                 readSize);
316     srcStream->Seek(positionRecord);
317     if (!flag || readSize != compressDataSize_) {
318         JPEG_HW_LOGE("failed to read input data, readSize=%{public}u", readSize);
319         return false;
320     }
321     return true;
322 }
323 
ReadTwoBytes(ImagePlugin::InputDataStream * srcStream,unsigned int pos,bool & flag)324 uint16_t JpegHardwareDecoder::ReadTwoBytes(ImagePlugin::InputDataStream* srcStream, unsigned int pos, bool& flag)
325 {
326     static constexpr int ZERO = 0;
327     static constexpr int ONE = 1;
328     static constexpr int TWO = 2;
329     static constexpr int BITS_OFFSET = 8;
330     uint8_t* readBuffer = new (std::nothrow) uint8_t[TWO];
331     uint16_t result = 0xFFFF;
332     if (readBuffer == nullptr) {
333         JPEG_HW_LOGE("new readbuffer failed");
334         flag = false;
335     } else {
336         uint32_t readSize = 0;
337         srcStream->Seek(pos);
338         bool ret = srcStream->Read(TWO, readBuffer, TWO, readSize);
339         if (!ret) {
340             JPEG_HW_LOGE("read input stream failed.");
341             flag = false;
342         }
343         result = static_cast<uint16_t>((readBuffer[ZERO] << BITS_OFFSET) + readBuffer[ONE]);
344         delete[] readBuffer;
345     }
346     return result;
347 }
348 
GetCompressedDataStart(ImagePlugin::InputDataStream * srcStream)349 bool JpegHardwareDecoder::GetCompressedDataStart(ImagePlugin::InputDataStream* srcStream)
350 {
351     unsigned int fileSize = static_cast<unsigned int>(srcStream->GetStreamSize());
352     if (fileSize == 0) {
353         JPEG_HW_LOGE("input stream is null ");
354         return false;
355     }
356     uint32_t positionRecord = srcStream->Tell();
357     srcStream->Seek(0);
358     unsigned int curPos = 0;
359     bool findFlag = false;
360     while (curPos + JpegMarker::MARKER_LEN <= fileSize) {
361         bool readSuccess = true;
362         uint16_t potentialMarker = ReadTwoBytes(srcStream, curPos, readSuccess);
363         if (!readSuccess) {
364             findFlag = false;
365             break;
366         }
367         if (potentialMarker < JpegMarker::MIN_MARKER || potentialMarker > JpegMarker::MAX_MARKER) {
368             ++curPos;
369             continue;
370         }
371         if (!JumpOverCurrentJpegMarker(srcStream, curPos, fileSize, potentialMarker)) {
372             break;
373         }
374         if (potentialMarker == JpegMarker::SOS) {
375             findFlag = true;
376             compressDataPos_ = curPos;
377             compressDataSize_ = fileSize - curPos;
378             break;
379         }
380     }
381     JPEG_HW_LOGI("input stream size:%{public}u compress data size:%{public}u", fileSize, compressDataSize_);
382     srcStream->Seek(positionRecord);
383     return findFlag;
384 }
385 
TryDmaPoolInBuff(ImagePlugin::InputDataStream * srcStream)386 bool JpegHardwareDecoder::TryDmaPoolInBuff(ImagePlugin::InputDataStream* srcStream)
387 {
388     ImageTrace imageTrace("JpegHardwareDecoder::TryDmaPoolInBuff");
389     PureStreamInfo curStreamInfo {compressDataPos_, compressDataSize_};
390     DmaBufferInfo allocBufferInfo {0, 0};
391     if (!DmaPool::GetInstance().AllocBufferInDmaPool(hwDecoder_, srcStream, inputBuffer_,
392         curStreamInfo, allocBufferInfo)) {
393         return false;
394     }
395     usedOffsetInPool_ = allocBufferInfo.allocatedBufferOffsetOfPool;
396     usedSizeInPool_ = allocBufferInfo.allocatedBufferSize;
397     return true;
398 }
399 
TryNormalInBuff(ImagePlugin::InputDataStream * srcStream)400 bool JpegHardwareDecoder::TryNormalInBuff(ImagePlugin::InputDataStream* srcStream)
401 {
402     ImageTrace imageTrace("JpegHardwareDecoder::TryNormalInBuff");
403     // step1. alloc Buffer
404     int32_t ret = hwDecoder_->AllocateInBuffer(inputBuffer_, compressDataSize_, CODEC_IMAGE_JPEG);
405     if (ret != HDF_SUCCESS) {
406         JPEG_HW_LOGE("failed to allocate input buffer, err=%{public}d", ret);
407         return false;
408     }
409     usedOffsetInPool_ = 0;
410     // step2. copysrc to buffer
411     BufferHandle *inputBufferHandle = inputBuffer_.buffer->GetBufferHandle();
412     if (inputBufferHandle == nullptr) {
413         JPEG_HW_LOGE("inputBufferHandle is nullptr");
414         return false;
415     }
416     inputBufferHandle->virAddr = mmap(nullptr, inputBufferHandle->size,
417                                       PROT_READ | PROT_WRITE, MAP_SHARED, inputBufferHandle->fd, 0);
418     if (inputBufferHandle->virAddr == MAP_FAILED) {
419         JPEG_HW_LOGE("failed to map input buffer");
420         return false;
421     }
422     if (!CopySrcToInputBuff(srcStream, inputBufferHandle)) {
423         munmap(inputBufferHandle->virAddr, inputBufferHandle->size);
424         JPEG_HW_LOGE("copy bitstream to input buffer failed");
425         return false;
426     }
427     ret = munmap(inputBufferHandle->virAddr, inputBufferHandle->size);
428     if (ret != 0) {
429         JPEG_HW_LOGE("failed to unmap input buffer, err=%{public}d", ret);
430     }
431 
432     return true;
433 }
434 
CopySrcImgToDecodeInputBuffer(ImagePlugin::InputDataStream * srcStream)435 bool JpegHardwareDecoder::CopySrcImgToDecodeInputBuffer(ImagePlugin::InputDataStream* srcStream)
436 {
437     // max size of pure jpeg bitstream to use DMA Pool is 256KB
438     constexpr uint32_t MAX_SIZE_USE_DMA_POOL = 256 * 1024;
439     if (!GetCompressedDataStart(srcStream)) {
440         JPEG_HW_LOGE("get compressed data start failed");
441         return false;
442     }
443     if (compressDataSize_ <= MAX_SIZE_USE_DMA_POOL) {
444         if (TryDmaPoolInBuff(srcStream)) {
445             useDmaPool_ = true;
446         }
447     }
448     if ((compressDataSize_ > MAX_SIZE_USE_DMA_POOL) || (!useDmaPool_)) {
449         if (!TryNormalInBuff(srcStream)) {
450             return false;
451         }
452     }
453     decodeInfo_.compressPos = usedOffsetInPool_;
454     return true;
455 }
456 
IsStandAloneJpegMarker(uint16_t marker)457 bool JpegHardwareDecoder::IsStandAloneJpegMarker(uint16_t marker)
458 {
459     auto iter = std::find(JpegMarker::STAND_ALONE_MARKER.begin(), JpegMarker::STAND_ALONE_MARKER.end(), marker);
460     return (iter != JpegMarker::STAND_ALONE_MARKER.end());
461 }
462 
JumpOverCurrentJpegMarker(ImagePlugin::InputDataStream * srcStream,unsigned int & curPos,unsigned int totalLen,uint16_t marker)463 bool JpegHardwareDecoder::JumpOverCurrentJpegMarker(ImagePlugin::InputDataStream* srcStream, unsigned int& curPos,
464                                                     unsigned int totalLen, uint16_t marker)
465 {
466     curPos += JpegMarker::MARKER_LEN;
467     if (curPos + JpegMarker::MARKER_LEN > totalLen) {
468         JPEG_HW_LOGE("invalid pos(cur=%{public}u, total=%{public}u) after jump over marker(%{public}u)",
469                      curPos, totalLen, marker);
470         return false;
471     }
472     if (IsStandAloneJpegMarker(marker)) {
473         return true;
474     }
475     // jump over related parameters for those who are not stand alone markers
476     bool readSuccess = true;
477     unsigned int skipBytes = static_cast<unsigned int>(ReadTwoBytes(srcStream, curPos, readSuccess));
478     if (!readSuccess) {
479         return false;
480     }
481     curPos += skipBytes;
482     if (curPos > totalLen) {
483         JPEG_HW_LOGE("invalid pos(cur=%{public}u, total=%{public}u) after jump over related parameters " \
484                      "for marker(%{public}u)", curPos, totalLen, marker);
485         return false;
486     }
487     return true;
488 }
489 
PrepareInputData(SkCodec * codec,ImagePlugin::InputDataStream * srcStream)490 bool JpegHardwareDecoder::PrepareInputData(SkCodec *codec, ImagePlugin::InputDataStream *srcStream)
491 {
492     Media::ImageTrace imageTrace("PrepareInputData");
493     LifeSpanTimer decodeTimer("prepare input data");
494     jpeg_decompress_struct* jpegCompressInfo = GetJpegCompressInfo(codec);
495     if (jpegCompressInfo == nullptr || srcStream == nullptr) {
496         JPEG_HW_LOGE("failed to get jpeg compress info or invalid input stream");
497         return false;
498     }
499     bool ret = AssembleJpegImgHeader(jpegCompressInfo);
500     ret = ret && CopySrcImgToDecodeInputBuffer(srcStream);
501     return ret;
502 }
503 
InitDecoder()504 bool JpegHardwareDecoder::InitDecoder()
505 {
506     LifeSpanTimer decodeTimer("init decoder");
507     if (hwDecoder_ == nullptr) {
508         JPEG_HW_LOGE("failed to get ICodecImage!");
509         return false;
510     }
511     int32_t ret = hwDecoder_->Init(CODEC_IMAGE_JPEG);
512     if (ret != HDF_SUCCESS) {
513         JPEG_HW_LOGE("failed to init decoder, err=%{public}d", ret);
514         return false;
515     }
516     hwDecoder_->NotifyPowerOn(CODEC_IMAGE_JPEG);
517     return true;
518 }
519 
DoDecode(CodecImageBuffer & outputBuffer)520 bool JpegHardwareDecoder::DoDecode(CodecImageBuffer& outputBuffer)
521 {
522     Media::ImageTrace imageTrace("DoDecode");
523     LifeSpanTimer decodeTimer("do decode");
524     int32_t ret = hwDecoder_->DoJpegDecode(inputBuffer_, outputBuffer, decodeInfo_);
525     if (ret != HDF_SUCCESS) {
526         JPEG_HW_LOGE("failed to do decode, err=%{public}d", ret);
527         return false;
528     }
529     return true;
530 }
531 
RecycleAllocatedResource()532 void JpegHardwareDecoder::RecycleAllocatedResource()
533 {
534     ImageTrace imageTrace("JpegHardwareDecoder::RecycleAllocatedResource");
535     if (useDmaPool_) {
536         DmaBufferInfo bufferInfo {usedSizeInPool_, usedOffsetInPool_};
537         DmaPool::GetInstance().RecycleBufferInDmaPool(bufferInfo);
538     }
539 }
540 } // namespace OHOS::ImagePlugin
541