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