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