1 /*
2 * Copyright (c) 2025 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 <fstream>
17 #include <map>
18 #include <securec.h>
19 #include "ext_stream.h"
20 #include "file_source_stream.h"
21 #include "v1_0/display_buffer_type.h"
22 #include "mock_jpeg_hw_decode_flow.h"
23
24 namespace OHOS::ImagePlugin {
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;
28
JpegHwDecoderFlow()29 JpegHwDecoderFlow::JpegHwDecoderFlow() : sampleSize_(1), outputColorFmt_(V1_2::PIXEL_FMT_YCRCB_420_SP)
30 {
31 bufferMgr_ = IDisplayBuffer::Get();
32 outputBuffer_.id = 0;
33 outputBuffer_.size = 0;
34 outputBuffer_.buffer = nullptr;
35 outputBuffer_.fenceFd = -1;
36 outputBuffer_.bufferRole = CODEC_IMAGE_JPEG;
37 }
38
~JpegHwDecoderFlow()39 JpegHwDecoderFlow::~JpegHwDecoderFlow()
40 {
41 bufferMgr_ = nullptr;
42 }
43
InitDecoder()44 bool JpegHwDecoderFlow::InitDecoder()
45 {
46 if (!hwDecoder_.InitDecoder()) {
47 JPEG_HW_LOGE("init jpeg hardware decoder failed");
48 return false;
49 }
50 return true;
51 }
52
AllocOutputBuffer()53 bool JpegHwDecoderFlow::AllocOutputBuffer()
54 {
55 AllocInfo alloc = {
56 .width = scaledImgSize_.width,
57 .height = scaledImgSize_.height,
58 .usage = V1_2::HBM_USE_CPU_READ | V1_2::HBM_USE_CPU_WRITE | V1_2::HBM_USE_MEM_DMA,
59 .format = outputColorFmt_
60 };
61 BufferHandle *handle = nullptr;
62 int32_t ret = bufferMgr_->AllocMem(alloc, handle);
63 if (ret != HDF_SUCCESS) {
64 JPEG_HW_LOGE("failed to alloc output buffer, err=%{public}d", ret);
65 return false;
66 }
67 if (outputColorFmt_ == V1_2::PIXEL_FMT_RGBA_8888) {
68 static constexpr uint32_t bitDepthForRgba = 4;
69 outputBufferSize_.width = static_cast<int32_t>((handle->stride) / bitDepthForRgba);
70 } else { // V1_2::PIXEL_FMT_YCRCB_420_SP
71 outputBufferSize_.width = static_cast<int32_t>(handle->stride);
72 }
73 outputBufferSize_.height = static_cast<int32_t>(handle->height);
74 outputBuffer_.buffer = new NativeBuffer(handle);
75 return true;
76 }
77
DoDecode()78 bool JpegHwDecoderFlow::DoDecode()
79 {
80 std::unique_ptr<Media::SourceStream> stream = Media::FileSourceStream::CreateSourceStream(inputFile_);
81 ImagePlugin::InputDataStream* inputStream = stream.get();
82 std::unique_ptr<SkCodec> demoCodec = SkCodec::MakeFromStream(std::make_unique<ExtStream>(inputStream));
83 auto ret = hwDecoder_.Decode(demoCodec.get(), inputStream, orgImgSize_, sampleSize_, outputBuffer_);
84 if (ret != 0) {
85 JPEG_HW_LOGE("failed to do jpeg hardware decode, err=%{public}u", ret);
86 return false;
87 }
88 return true;
89 }
90
DumpDecodeResult()91 bool JpegHwDecoderFlow::DumpDecodeResult()
92 {
93 JPEG_HW_LOGI("dump decode result");
94 auto getColorDesc = [this]()->std::string {
95 if (outputColorFmt_ == V1_2::PIXEL_FMT_YCRCB_420_SP) {
96 return "YUV";
97 } else if (outputColorFmt_ == V1_2::PIXEL_FMT_RGBA_8888) {
98 return "RGB";
99 }
100 return "UnknownColorFormat";
101 };
102
103 constexpr int maxPathLen = 256;
104 char outputFilePath[maxPathLen] = {0};
105 std::string colorDesc = getColorDesc();
106 int ret = sprintf_s(outputFilePath, sizeof(outputFilePath), "%s/out_%d(%d)x%d_org_%dx%d_%s.bin",
107 outputPath_.c_str(), scaledImgSize_.width, outputBufferSize_.width, scaledImgSize_.height,
108 orgImgSize_.width, orgImgSize_.height, colorDesc.c_str());
109 if (ret == -1) {
110 JPEG_HW_LOGE("failed to create dump file");
111 return false;
112 }
113
114 std::ofstream dumpOutFile;
115 dumpOutFile.open(std::string(outputFilePath), std::ios_base::binary | std::ios_base::trunc);
116 if (!dumpOutFile.is_open()) {
117 JPEG_HW_LOGE("failed to dump decode result");
118 return false;
119 }
120
121 BufferHandle *outputHandle = outputBuffer_.buffer->GetBufferHandle();
122 bufferMgr_->Mmap(*outputHandle);
123 (void)bufferMgr_->InvalidateCache(*outputHandle);
124 dumpOutFile.write(reinterpret_cast<char*>(outputHandle->virAddr), outputHandle->size);
125 dumpOutFile.flush();
126 (void)bufferMgr_->FlushCache(*outputHandle);
127 (void)bufferMgr_->Unmap(*outputHandle);
128 dumpOutFile.close();
129 return true;
130 }
131
UserColorFmtToPixelFmt(UserColorFormat usrColorFmt)132 std::optional<V1_2::PixelFormat> JpegHwDecoderFlow::UserColorFmtToPixelFmt(UserColorFormat usrColorFmt)
133 {
134 static const std::map<UserColorFormat, V1_2::PixelFormat> colorMap = {
135 { UserColorFormat::YUV, V1_2::PIXEL_FMT_YCRCB_420_SP },
136 { UserColorFormat::RGB, V1_2::PIXEL_FMT_RGBA_8888 }
137 };
138 auto iter = colorMap.find(usrColorFmt);
139 if (iter == colorMap.end()) {
140 JPEG_HW_LOGE("unsupported color format(%{public}d)", static_cast<int>(usrColorFmt));
141 return std::nullopt;
142 }
143 return iter->second;
144 }
145
Run(const CommandOpt & opt,bool needDumpOutput)146 bool JpegHwDecoderFlow::Run(const CommandOpt& opt, bool needDumpOutput)
147 {
148 JPEG_HW_LOGI("jpeg hardware decode demo start");
149 std::optional<V1_2::PixelFormat> colorFmt = UserColorFmtToPixelFmt(opt.colorFmt);
150 if (!colorFmt.has_value()) {
151 JPEG_HW_LOGE("jpeg hardware decode demo failed");
152 return false;
153 }
154 inputFile_ = opt.inputFile;
155 outputPath_ = opt.outputPath;
156 outputColorFmt_ = colorFmt.value();
157 orgImgSize_.width = opt.width;
158 orgImgSize_.height = opt.height;
159 sampleSize_ = opt.sampleSize;
160 scaledImgSize_.width = static_cast<int32_t>(AlignUp(opt.width / opt.sampleSize, ALIGN_8));
161 scaledImgSize_.height = static_cast<int32_t>(AlignUp(opt.height / opt.sampleSize, ALIGN_8));
162 JPEG_HW_LOGD("orgImgSize=[%{public}ux%{public}u], scaledImgSize=[%{public}ux%{public}u], sampleSize=%{public}u",
163 orgImgSize_.width, orgImgSize_.height, scaledImgSize_.width, scaledImgSize_.height, sampleSize_);
164 bool ret = InitDecoder();
165 ret = ret && AllocOutputBuffer();
166 ret = ret && DoDecode();
167 if (needDumpOutput) {
168 ret = ret && DumpDecodeResult();
169 }
170 if (ret) {
171 JPEG_HW_LOGI("jpeg hardware decode demo succeed");
172 } else {
173 JPEG_HW_LOGE("jpeg hardware decode demo failed");
174 }
175 return ret;
176 }
177 } // namespace OHOS::ImagePlugin