1 /*
2 * Copyright (C) 2022 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 #include "raw_decoder.h"
16 #include "hilog/log.h"
17 #include "log_tags.h"
18 #include "buffer_source_stream.h"
19 #include "jpeg_decoder.h"
20 #include "raw_stream.h"
21 namespace OHOS {
22 namespace ImagePlugin {
23 using namespace OHOS::HiviewDFX;
24 using namespace MultimediaPlugin;
25 using namespace Media;
26 namespace {
27 constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "RawDecoder" };
28 constexpr uint32_t RAW_IMAGE_NUM = 1;
29 }
30
RawDecoder()31 RawDecoder::RawDecoder()
32 {
33 HiLog::Debug(LABEL, "create IN");
34
35 HiLog::Debug(LABEL, "create OUT");
36 }
37
~RawDecoder()38 RawDecoder::~RawDecoder()
39 {
40 HiLog::Debug(LABEL, "release IN");
41
42 Reset();
43
44 HiLog::Debug(LABEL, "release OUT");
45 }
46
Reset()47 void RawDecoder::Reset()
48 {
49 HiLog::Debug(LABEL, "Reset IN");
50
51 inputStream_ = nullptr;
52 state_ = RawDecodingState::UNDECIDED;
53
54 PixelDecodeOptions opts;
55 opts_ = opts;
56
57 PlImageInfo info;
58 info_ = info;
59
60 rawStream_ = nullptr;
61
62 // PIEX used.
63 jpegStream_ = nullptr;
64 jpegDecoder_ = nullptr;
65
66 HiLog::Debug(LABEL, "Reset OUT");
67 }
68
HasProperty(std::string key)69 bool RawDecoder::HasProperty(std::string key)
70 {
71 HiLog::Debug(LABEL, "HasProperty IN key=[%{public}s]", key.c_str());
72
73 HiLog::Debug(LABEL, "HasProperty OUT");
74 return false;
75 }
76
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & progContext)77 uint32_t RawDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &progContext)
78 {
79 HiLog::Debug(LABEL, "PromoteIncrementalDecode index=%{public}u", index);
80 return Media::ERR_IMAGE_DATA_UNSUPPORT;
81 }
82
GetTopLevelImageNum(uint32_t & num)83 uint32_t RawDecoder::GetTopLevelImageNum(uint32_t &num)
84 {
85 num = RAW_IMAGE_NUM;
86 HiLog::Debug(LABEL, "GetTopLevelImageNum, num=%{public}u", num);
87 return Media::SUCCESS;
88 }
89
SetSource(InputDataStream & sourceStream)90 void RawDecoder::SetSource(InputDataStream &sourceStream)
91 {
92 HiLog::Debug(LABEL, "SetSource IN");
93
94 inputStream_ = &sourceStream;
95 rawStream_ = std::make_unique<RawStream>(sourceStream);
96
97 state_ = RawDecodingState::SOURCE_INITED;
98
99 HiLog::Debug(LABEL, "SetSource OUT");
100 }
101
SetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)102 uint32_t RawDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
103 {
104 HiLog::Debug(LABEL, "SetDecodeOptions IN index=%{public}u", index);
105
106 if (index >= RAW_IMAGE_NUM) {
107 HiLog::Error(LABEL, "[SetDecodeOptions] decode image index[%{public}u], out of range[%{public}u].",
108 index, RAW_IMAGE_NUM);
109 return Media::ERR_IMAGE_INVALID_PARAMETER;
110 }
111
112 HiLog::Debug(LABEL, "SetDecodeOptions opts, pixelFormat=%{public}d, alphaType=%{public}d, "
113 "colorSpace=%{public}d, size=(%{public}u, %{public}u), state=%{public}d",
114 static_cast<int32_t>(opts.desiredPixelFormat), static_cast<int32_t>(opts.desireAlphaType),
115 static_cast<int32_t>(opts.desiredColorSpace), opts.desiredSize.width, opts.desiredSize.height, state_);
116
117 if (state_ < RawDecodingState::SOURCE_INITED) {
118 HiLog::Error(LABEL, "[SetDecodeOptions] set decode options failed for state %{public}d.", state_);
119 return Media::ERR_MEDIA_INVALID_OPERATION;
120 }
121
122 if (state_ >= RawDecodingState::IMAGE_DECODING) {
123 state_ = RawDecodingState::SOURCE_INITED;
124 }
125
126 if (state_ < RawDecodingState::BASE_INFO_PARSED) {
127 uint32_t ret = DoDecodeHeader();
128 if (ret != Media::SUCCESS) {
129 state_ = RawDecodingState::BASE_INFO_PARSING;
130 HiLog::Error(LABEL, "[SetDecodeOptions] decode header error on set decode options:%{public}u.", ret);
131 return ret;
132 }
133
134 state_ = RawDecodingState::BASE_INFO_PARSED;
135 }
136
137 // only state RawDecodingState::BASE_INFO_PARSED can go here.
138 uint32_t ret = DoSetDecodeOptions(index, opts, info);
139 if (ret != Media::SUCCESS) {
140 state_ = RawDecodingState::BASE_INFO_PARSING;
141 HiLog::Error(LABEL, "[SetDecodeOptions] do set decode options:%{public}u.", ret);
142 return ret;
143 }
144
145 state_ = RawDecodingState::IMAGE_DECODING;
146
147 HiLog::Debug(LABEL, "SetDecodeOptions OUT");
148 return Media::SUCCESS;
149 }
150
GetImageSize(uint32_t index,PlSize & size)151 uint32_t RawDecoder::GetImageSize(uint32_t index, PlSize &size)
152 {
153 HiLog::Debug(LABEL, "GetImageSize IN index=%{public}u", index);
154
155 if (index >= RAW_IMAGE_NUM) {
156 HiLog::Error(LABEL, "[GetImageSize] decode image index[%{public}u], out of range[%{public}u].",
157 index, RAW_IMAGE_NUM);
158 return Media::ERR_IMAGE_INVALID_PARAMETER;
159 }
160
161 if (state_ < RawDecodingState::SOURCE_INITED) {
162 HiLog::Error(LABEL, "[GetImageSize] get image size failed for state %{public}d.", state_);
163 return ERR_MEDIA_INVALID_OPERATION;
164 }
165
166 if (state_ >= RawDecodingState::BASE_INFO_PARSED) {
167 size = info_.size;
168 HiLog::Debug(LABEL, "GetImageSize OUT size=(%{public}u, %{public}u)", size.width, size.height);
169 return Media::SUCCESS;
170 }
171
172 // only state RawDecodingState::SOURCE_INITED and RawDecodingState::BASE_INFO_PARSING can go here.
173 uint32_t ret = DoDecodeHeader();
174 if (ret != Media::SUCCESS) {
175 HiLog::Error(LABEL, "[GetImageSize]decode header error on get image size, ret:%{public}u.", ret);
176 state_ = RawDecodingState::BASE_INFO_PARSING;
177 return ret;
178 }
179
180 ret = DoGetImageSize(index, size);
181 if (ret != Media::SUCCESS) {
182 HiLog::Error(LABEL, "[GetImageSize]do get image size, ret:%{public}u.", ret);
183 state_ = RawDecodingState::BASE_INFO_PARSING;
184 return ret;
185 }
186
187 state_ = RawDecodingState::BASE_INFO_PARSED;
188
189 HiLog::Debug(LABEL, "GetImageSize OUT size=(%{public}u, %{public}u)", size.width, size.height);
190 return Media::SUCCESS;
191 }
192
Decode(uint32_t index,DecodeContext & context)193 uint32_t RawDecoder::Decode(uint32_t index, DecodeContext &context)
194 {
195 HiLog::Debug(LABEL, "Decode IN index=%{public}u", index);
196
197 if (index >= RAW_IMAGE_NUM) {
198 HiLog::Error(LABEL, "[Decode] decode image index:[%{public}u] out of range:[%{public}u].",
199 index, RAW_IMAGE_NUM);
200 return Media::ERR_IMAGE_INVALID_PARAMETER;
201 }
202 if (state_ < RawDecodingState::IMAGE_DECODING) {
203 HiLog::Error(LABEL, "[Decode] decode failed for state %{public}d.", state_);
204 return Media::ERR_MEDIA_INVALID_OPERATION;
205 }
206
207 uint32_t ret = DoDecode(index, context);
208 if (ret == Media::SUCCESS) {
209 state_ = RawDecodingState::IMAGE_DECODED;
210 HiLog::Info(LABEL, "[Decode] success.");
211 } else {
212 state_ = RawDecodingState::IMAGE_ERROR;
213 HiLog::Error(LABEL, "[Decode] fail, ret=%{public}u", ret);
214 }
215
216 HiLog::Debug(LABEL, "Decode OUT");
217 return ret;
218 }
219
DoDecodeHeader()220 uint32_t RawDecoder::DoDecodeHeader()
221 {
222 HiLog::Debug(LABEL, "DoDecodeHeader IN");
223
224 if (piex::IsRaw(rawStream_.get())) {
225 jpegDecoder_ = nullptr;
226 jpegStream_ = nullptr;
227 uint32_t ret = DoDecodeHeaderByPiex();
228 if (ret != Media::SUCCESS) {
229 HiLog::Error(LABEL, "DoDecodeHeader piex header decode fail.");
230 return ret;
231 }
232
233 if (jpegDecoder_ != nullptr) {
234 HiLog::Info(LABEL, "DoDecodeHeader piex header decode success.");
235 return Media::SUCCESS;
236 }
237 }
238
239 uint32_t ret = Media::ERR_IMAGE_DATA_UNSUPPORT;
240 HiLog::Error(LABEL, "DoDecodeHeader header decode fail, ret=[%{public}u]", ret);
241
242 HiLog::Debug(LABEL, "DoDecodeHeader OUT");
243 return ret;
244 }
245
DoDecodeHeaderByPiex()246 uint32_t RawDecoder::DoDecodeHeaderByPiex()
247 {
248 HiLog::Debug(LABEL, "DoDecodeHeaderByPiex IN");
249
250 piex::PreviewImageData imageData;
251 piex::Error error = piex::GetPreviewImageData(rawStream_.get(), &imageData);
252 if (error == piex::Error::kFail) {
253 HiLog::Error(LABEL, "DoDecodeHeaderByPiex get preview fail");
254 return Media::ERR_IMAGE_DATA_ABNORMAL;
255 }
256
257 piex::Image piexImage;
258 bool hasImage = false;
259 if (error == piex::Error::kOk) {
260 if ((imageData.preview.format == piex::Image::kJpegCompressed) && (imageData.preview.length > 0)) {
261 piexImage = imageData.preview;
262 hasImage = true;
263 }
264 }
265
266 if (!hasImage) {
267 HiLog::Debug(LABEL, "DoDecodeHeaderByPiex OUT 2");
268 return Media::SUCCESS;
269 }
270
271 uint32_t size = piexImage.length;
272 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(size);
273 error = rawStream_->GetData(piexImage.offset, size, data.get());
274 if (error != piex::Error::kOk) {
275 HiLog::Error(LABEL, "DoDecodeHeaderByPiex getdata fail");
276 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
277 }
278
279 jpegStream_ = BufferSourceStream::CreateSourceStream(data.get(), size);
280 if (!jpegStream_) {
281 HiLog::Error(LABEL, "DoDecodeHeaderByPiex create sourcestream fail");
282 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
283 }
284
285 data = nullptr;
286 jpegDecoder_ = std::make_unique<JpegDecoder>();
287 jpegDecoder_->SetSource(*(jpegStream_.get()));
288
289 HiLog::Debug(LABEL, "DoDecodeHeaderByPiex OUT");
290 return Media::SUCCESS;
291 }
292
DoSetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)293 uint32_t RawDecoder::DoSetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
294 {
295 HiLog::Debug(LABEL, "DoSetDecodeOptions IN index=%{public}u", index);
296 uint32_t ret;
297 opts_ = opts;
298 if (jpegDecoder_ != nullptr) {
299 HiLog::Info(LABEL, "DoSetDecodeOptions, set decode options for JpegDecoder");
300 ret = jpegDecoder_->SetDecodeOptions(index, opts_, info_);
301 } else {
302 HiLog::Error(LABEL, "DoSetDecodeOptions, unsupport");
303 ret = Media::ERR_IMAGE_DATA_UNSUPPORT;
304 }
305 info = info_;
306
307 if (ret == Media::SUCCESS) {
308 HiLog::Info(LABEL, "DoSetDecodeOptions set decode options success.");
309 } else {
310 HiLog::Error(LABEL, "DoSetDecodeOptions set decode options fail, ret=[%{public}u]", ret);
311 }
312
313 HiLog::Debug(LABEL, "DoSetDecodeOptions OUT pixelFormat=%{public}d, alphaType=%{public}d, "
314 "colorSpace=%{public}d, size=(%{public}u, %{public}u)",
315 static_cast<int32_t>(info.pixelFormat), static_cast<int32_t>(info.alphaType),
316 static_cast<int32_t>(info.colorSpace), info.size.width, info.size.height);
317 return ret;
318 }
319
DoGetImageSize(uint32_t index,PlSize & size)320 uint32_t RawDecoder::DoGetImageSize(uint32_t index, PlSize &size)
321 {
322 HiLog::Debug(LABEL, "DoGetImageSize IN index=%{public}u", index);
323 uint32_t ret;
324
325 if (jpegDecoder_ != nullptr) {
326 HiLog::Info(LABEL, "DoGetImageSize, get image size for JpegDecoder");
327 ret = jpegDecoder_->GetImageSize(index, info_.size);
328 } else {
329 HiLog::Error(LABEL, "DoGetImageSize, unsupport");
330 ret = Media::ERR_IMAGE_DATA_UNSUPPORT;
331 }
332 size = info_.size;
333
334 if (ret == Media::SUCCESS) {
335 HiLog::Info(LABEL, "DoGetImageSize, get image size success.");
336 } else {
337 HiLog::Error(LABEL, "DoGetImageSize, get image size fail, ret=[%{public}u]", ret);
338 }
339
340 HiLog::Debug(LABEL, "DoGetImageSize OUT size=(%{public}u, %{public}u)", size.width, size.height);
341 return ret;
342 }
343
DoDecode(uint32_t index,DecodeContext & context)344 uint32_t RawDecoder::DoDecode(uint32_t index, DecodeContext &context)
345 {
346 HiLog::Debug(LABEL, "DoDecode IN index=%{public}u", index);
347 uint32_t ret;
348
349 if (jpegDecoder_ != nullptr) {
350 HiLog::Info(LABEL, "DoDecode decode by JpegDecoder.");
351 ret = jpegDecoder_->Decode(index, context);
352 } else {
353 HiLog::Error(LABEL, "DoDecode decode unsupport.");
354 ret = Media::ERR_IMAGE_DATA_UNSUPPORT;
355 }
356
357 if (ret == Media::SUCCESS) {
358 HiLog::Info(LABEL, "DoDecode decode success.");
359 } else {
360 HiLog::Error(LABEL, "DoDecode decode fail, ret=%{public}u", ret);
361 }
362
363 HiLog::Debug(LABEL, "DoDecode OUT ret=%{public}u", ret);
364 return ret;
365 }
366 } // namespace ImagePlugin
367 } // namespace OHOS
368