1 /*
2 * Copyright (C) 2024 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 "thumbnail_source_loading.h"
17
18 #include <fcntl.h>
19
20 #include "dfx_manager.h"
21 #include "dfx_utils.h"
22 #include "directory_ex.h"
23 #include "image_source.h"
24 #include "media_exif.h"
25 #include "media_file_utils.h"
26 #include "medialibrary_tracer.h"
27 #include "post_proc.h"
28 #include "thumbnail_utils.h"
29 #include "thumbnail_const.h"
30
31 using namespace std;
32
33 namespace OHOS {
34 namespace Media {
35
36 const std::string LOCAL_MEDIA_PATH = "/storage/media/local/files/";
37
38 const std::unordered_map<SourceState, SourceState> SourceLoader::LOCAL_SOURCE_LOADING_STATES = {
39 { SourceState::BEGIN, SourceState::LOCAL_ORIGIN },
40 { SourceState::LOCAL_ORIGIN, SourceState::FINISH },
41 };
42
43 const std::unordered_map<SourceState, SourceState> SourceLoader::CLOUD_SOURCE_LOADING_STATES = {
44 { SourceState::BEGIN, SourceState::CLOUD_THUMB },
45 { SourceState::CLOUD_THUMB, SourceState::CLOUD_LCD },
46 { SourceState::CLOUD_LCD, SourceState::CLOUD_ORIGIN },
47 { SourceState::CLOUD_ORIGIN, SourceState::FINISH },
48 };
49
50 const std::unordered_map<SourceState, SourceState> SourceLoader::ALL_SOURCE_LOADING_STATES = {
51 { SourceState::BEGIN, SourceState::LOCAL_THUMB },
52 { SourceState::LOCAL_THUMB, SourceState::LOCAL_LCD },
53 { SourceState::LOCAL_LCD, SourceState::LOCAL_ORIGIN },
54 { SourceState::LOCAL_ORIGIN, SourceState::CLOUD_LCD },
55 { SourceState::CLOUD_LCD, SourceState::CLOUD_ORIGIN },
56 { SourceState::CLOUD_ORIGIN, SourceState::FINISH },
57 };
58
59 // For cloud video, generating thumbnail foreground in LOCAL_ORIGIN state may download its source video.
60 const std::unordered_map<SourceState, SourceState> SourceLoader::ALL_SOURCE_LOADING_CLOUD_VIDEO_STATES = {
61 { SourceState::BEGIN, SourceState::LOCAL_THUMB },
62 { SourceState::LOCAL_THUMB, SourceState::LOCAL_LCD },
63 { SourceState::LOCAL_LCD, SourceState::CLOUD_LCD },
64 { SourceState::CLOUD_LCD, SourceState::CLOUD_ORIGIN },
65 { SourceState::CLOUD_ORIGIN, SourceState::FINISH },
66 };
67
68 const std::unordered_map<SourceState, SourceState> SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES = {
69 { SourceState::BEGIN, SourceState::CLOUD_LCD },
70 { SourceState::CLOUD_LCD, SourceState::CLOUD_ORIGIN },
71 { SourceState::CLOUD_ORIGIN, SourceState::FINISH },
72 };
73
74 const std::unordered_map<SourceState, SourceState> SourceLoader::LOCAL_LCD_SOURCE_LOADING_STATES = {
75 { SourceState::BEGIN, SourceState::LOCAL_LCD },
76 { SourceState::LOCAL_LCD, SourceState::LOCAL_ORIGIN },
77 { SourceState::LOCAL_ORIGIN, SourceState::FINISH },
78 };
79
80 const std::unordered_map<SourceState, SourceState> SourceLoader::UPGRADE_SOURCE_LOADING_STATES = {
81 { SourceState::BEGIN, SourceState::LOCAL_ORIGIN },
82 { SourceState::LOCAL_ORIGIN, SourceState::CLOUD_ORIGIN },
83 { SourceState::CLOUD_ORIGIN, SourceState::FINISH },
84 };
85
86 const std::unordered_map<SourceState, SourceState> SourceLoader::UPGRADE_VIDEO_SOURCE_LOADING_STATES = {
87 { SourceState::BEGIN, SourceState::LOCAL_ORIGIN },
88 { SourceState::LOCAL_ORIGIN, SourceState::CLOUD_LCD },
89 { SourceState::CLOUD_LCD, SourceState::FINISH },
90 };
91
GetLocalThumbnailPath(const std::string & path,const std::string & key)92 std::string GetLocalThumbnailPath(const std::string &path, const std::string &key)
93 {
94 if (path.length() < ROOT_MEDIA_DIR.length()) {
95 return "";
96 }
97 std::string suffix = (key == "") ? "" : "/" + key + ".jpg";
98 return LOCAL_MEDIA_PATH + ((key == "") ? "" : ".thumbs/") + path.substr(ROOT_MEDIA_DIR.length()) + suffix;
99 }
100
GetLcdExPath(const std::string & path)101 std::string GetLcdExPath(const std::string &path)
102 {
103 if (path.length() < ROOT_MEDIA_DIR.length()) {
104 return "";
105 }
106 std::string suffix = "/THM_EX/" + THUMBNAIL_LCD_SUFFIX + ".jpg";
107 return ROOT_MEDIA_DIR + ".thumbs/" + path.substr(ROOT_MEDIA_DIR.length()) + suffix;
108 }
109
IsLocalSourceAvailable(const std::string & path)110 bool IsLocalSourceAvailable(const std::string& path)
111 {
112 char tmpPath[PATH_MAX] = { 0 };
113 if (realpath(path.c_str(), tmpPath) == nullptr) {
114 // it's alright if source loading fails here, just move on to next source
115 MEDIA_ERR_LOG("SourceLoader path to realPath is nullptr: errno: %{public}d, %{public}s",
116 errno, DfxUtils::GetSafePath(path).c_str());
117 return false;
118 }
119
120 FILE* filePtr = fopen(tmpPath, "rb");
121 if (filePtr == nullptr) {
122 MEDIA_ERR_LOG("SourceLoader open local file fail: errno: %{public}d, %{public}s",
123 errno, DfxUtils::GetSafePath(path).c_str());
124 return false;
125 }
126 if (fclose(filePtr) != E_OK) {
127 MEDIA_ERR_LOG("SourceLoader close filePtr fail: errno: %{public}d, %{public}s",
128 errno, DfxUtils::GetSafePath(path).c_str());
129 return false;
130 }
131 return true;
132 }
133
IsCloudSourceAvailable(const std::string & path)134 bool IsCloudSourceAvailable(const std::string& path)
135 {
136 string absFilePath;
137 if (!PathToRealPath(path, absFilePath)) {
138 MEDIA_ERR_LOG("Not real file path: errno: %{public}d, %{public}s", errno, DfxUtils::GetSafePath(path).c_str());
139 return false;
140 }
141
142 int fd = open(absFilePath.c_str(), O_RDONLY);
143 if (fd < 0) {
144 MEDIA_ERR_LOG("open cloud file fail: errno: %{public}d, %{public}s",
145 errno, DfxUtils::GetSafePath(path).c_str());
146 return false;
147 }
148 close(fd);
149 return true;
150 }
151
NeedAutoResize(const Size & size)152 bool NeedAutoResize(const Size &size)
153 {
154 // Only small thumbnails need to be scaled after decoding, others should resized while decoding.
155 return size.width > SHORT_SIDE_THRESHOLD && size.height > SHORT_SIDE_THRESHOLD;
156 }
157
GenDecodeOpts(const Size & sourceSize,const Size & targetSize,DecodeOptions & decodeOpts)158 bool GenDecodeOpts(const Size &sourceSize, const Size &targetSize, DecodeOptions &decodeOpts)
159 {
160 if (targetSize.width == 0) {
161 MEDIA_ERR_LOG("Failed to generate decodeOpts, scale size contains zero");
162 return false;
163 }
164 decodeOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
165 if (NeedAutoResize(targetSize)) {
166 decodeOpts.desiredSize = targetSize;
167 return true;
168 }
169
170 int32_t decodeScale = 1;
171 int32_t scaleFactor = sourceSize.width / targetSize.width;
172 while (scaleFactor /= DECODE_SCALE_BASE) {
173 decodeScale *= DECODE_SCALE_BASE;
174 }
175 decodeOpts.desiredSize = {
176 std::ceil(sourceSize.width / decodeScale),
177 std::ceil(sourceSize.height / decodeScale),
178 };
179 return true;
180 }
181
ConvertDecodeSize(ThumbnailData & data,const Size & sourceSize,Size & desiredSize)182 Size ConvertDecodeSize(ThumbnailData &data, const Size &sourceSize, Size &desiredSize)
183 {
184 int width = sourceSize.width;
185 int height = sourceSize.height;
186 if (!ThumbnailUtils::ResizeThumb(width, height)) {
187 MEDIA_ERR_LOG("ResizeThumb failed");
188 return {0, 0};
189 }
190 Size thumbDesiredSize = {width, height};
191 data.thumbDesiredSize = thumbDesiredSize;
192 float desiredScale = static_cast<float>(thumbDesiredSize.height) / static_cast<float>(thumbDesiredSize.width);
193 float sourceScale = static_cast<float>(sourceSize.height) / static_cast<float>(sourceSize.width);
194 float scale = 1.0f;
195 if (sourceScale - desiredScale <= EPSILON) {
196 scale = (float)thumbDesiredSize.height / sourceSize.height;
197 } else {
198 scale = (float)thumbDesiredSize.width / sourceSize.width;
199 }
200 scale = scale < 1.0f ? scale : 1.0f;
201 Size thumbDecodeSize = {
202 static_cast<int32_t> (scale * sourceSize.width),
203 static_cast<int32_t> (scale * sourceSize.height),
204 };
205
206 width = sourceSize.width;
207 height = sourceSize.height;
208 if (!ThumbnailUtils::ResizeLcd(width, height)) {
209 MEDIA_ERR_LOG("ResizeLcd failed");
210 return {0, 0};
211 }
212 Size lcdDesiredSize = {width, height};
213 data.lcdDesiredSize = lcdDesiredSize;
214
215 int lcdMinSide = std::min(lcdDesiredSize.width, lcdDesiredSize.height);
216 int thumbMinSide = std::min(thumbDesiredSize.width, thumbDesiredSize.height);
217 Size lcdDecodeSize = lcdMinSide < thumbMinSide ? thumbDecodeSize : lcdDesiredSize;
218
219 if (data.loaderOpts.decodeInThumbSize) {
220 desiredSize = thumbDesiredSize;
221 return thumbDecodeSize;
222 } else if (data.needResizeLcd) {
223 desiredSize = lcdDesiredSize;
224 return lcdDecodeSize;
225 } else {
226 desiredSize = lcdDesiredSize;
227 return lcdDesiredSize;
228 }
229 }
230
SwitchToNextState(ThumbnailData & data,SourceState & state)231 void SwitchToNextState(ThumbnailData &data, SourceState &state)
232 {
233 if (state == SourceState::FINISH) {
234 MEDIA_INFO_LOG("SwitchToNextState current state is FINISH.");
235 return;
236 }
237 auto iter = data.loaderOpts.loadingStates.find(state);
238 if (iter == data.loaderOpts.loadingStates.end()) {
239 MEDIA_WARN_LOG("SwitchToNextState find next state error, current state:%{public}d",
240 static_cast<int32_t>(state));
241 return;
242 }
243 state = iter->second;
244 }
245
LoadImageSource(const std::string & path,uint32_t & err)246 unique_ptr<ImageSource> LoadImageSource(const std::string &path, uint32_t &err)
247 {
248 MediaLibraryTracer tracer;
249 tracer.Start("LoadImageSource");
250
251 SourceOptions opts;
252 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, err);
253 if (err != E_OK || !imageSource) {
254 MEDIA_ERR_LOG("Failed to LoadImageSource, pixelmap path: %{public}s exists: %{public}d",
255 path.c_str(), MediaFileUtils::IsFileExists(path));
256 DfxManager::GetInstance()->HandleThumbnailError(path, DfxType::IMAGE_SOURCE_CREATE, err);
257 return imageSource;
258 }
259 return imageSource;
260 }
261
CreateVideoFramePixelMap()262 bool SourceLoader::CreateVideoFramePixelMap()
263 {
264 MediaLibraryTracer tracer;
265 tracer.Start("CreateVideoFramePixelMap");
266 return ThumbnailUtils::LoadVideoFile(data_, desiredSize_);
267 }
268
SetCurrentStateFunction()269 void SourceLoader::SetCurrentStateFunction()
270 {
271 StateFunc stateFunc = STATE_FUNC_MAP.at(state_);
272 GetSourcePath = stateFunc.GetSourcePath;
273 IsSizeLargeEnough = stateFunc.IsSizeLargeEnough;
274 }
275
GeneratePictureSource(std::unique_ptr<ImageSource> & imageSource,const Size & targetSize)276 bool SourceLoader::GeneratePictureSource(std::unique_ptr<ImageSource> &imageSource, const Size &targetSize)
277 {
278 DecodingOptionsForPicture pictureOpts;
279 pictureOpts.desireAuxiliaryPictures = {AuxiliaryPictureType::GAINMAP};
280 uint32_t errorCode = ERR_OK;
281 auto picturePtr = imageSource->CreatePicture(pictureOpts, errorCode);
282 if (errorCode != E_OK || picturePtr == nullptr) {
283 MEDIA_ERR_LOG("Failed to GeneratePictureSource, CreatePicture failed, err: %{public}d, path %{public}s",
284 errorCode, DfxUtils::GetSafePath(data_.path).c_str());
285 return false;
286 }
287 std::shared_ptr<Picture> picture = std::move(picturePtr);
288 auto pixelMap = picture->GetMainPixel();
289 auto gainMap = picture->GetGainmapPixelMap();
290 if (pixelMap == nullptr) {
291 MEDIA_ERR_LOG("Failed to GeneratePictureSource, main pixelMap is nullptr, path %{public}s",
292 DfxUtils::GetSafePath(data_.path).c_str());
293 return false;
294 }
295 if (gainMap == nullptr) {
296 MEDIA_ERR_LOG("Failed to GeneratePictureSource, gainmap is nullptr, path %{public}s",
297 DfxUtils::GetSafePath(data_.path).c_str());
298 return false;
299 }
300 if (pixelMap->GetWidth() * pixelMap->GetHeight() == 0) {
301 MEDIA_ERR_LOG("Failed to GeneratePictureSource, pixelMap size invalid, width: %{public}d, height: %{public}d,"
302 "path %{public}s", pixelMap->GetWidth(), pixelMap->GetHeight(), DfxUtils::GetSafePath(data_.path).c_str());
303 return false;
304 }
305 float widthScale = (1.0f * targetSize.width) / pixelMap->GetWidth();
306 float heightScale = (1.0f * targetSize.height) / pixelMap->GetHeight();
307 pixelMap->resize(widthScale, heightScale);
308 gainMap->resize(widthScale, heightScale);
309 data_.source.SetPicture(picture);
310 return true;
311 }
312
GeneratePixelMapSource(std::unique_ptr<ImageSource> & imageSource,const Size & sourceSize,const Size & targetSize)313 bool SourceLoader::GeneratePixelMapSource(std::unique_ptr<ImageSource> &imageSource, const Size &sourceSize,
314 const Size &targetSize)
315 {
316 DecodeOptions decodeOpts;
317 uint32_t err = ERR_OK;
318 if (!GenDecodeOpts(sourceSize, targetSize, decodeOpts)) {
319 MEDIA_ERR_LOG("SourceLoader failed to generate decodeOpts, pixelmap path %{public}s",
320 DfxUtils::GetSafePath(data_.path).c_str());
321 return false;
322 }
323 std::shared_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
324 if (err != E_OK || pixelMap == nullptr) {
325 MEDIA_ERR_LOG("SourceLoader failed to CreatePixelMap, err: %{public}d, pixelmap path %{public}s",
326 err, DfxUtils::GetSafePath(data_.path).c_str());
327 DfxManager::GetInstance()->HandleThumbnailError(data_.path, DfxType::IMAGE_SOURCE_CREATE_PIXELMAP, err);
328 return false;
329 }
330 if (!NeedAutoResize(targetSize) && !ThumbnailUtils::ScaleTargetPixelMap(pixelMap, targetSize,
331 Media::AntiAliasingOption::HIGH)) {
332 MEDIA_ERR_LOG("SourceLoader fail to scaleTarget, path %{public}s", DfxUtils::GetSafePath(data_.path).c_str());
333 return false;
334 }
335 data_.source.SetPixelMap(pixelMap);
336 return true;
337 }
338
CreateImagePixelMap(const std::string & sourcePath)339 bool SourceLoader::CreateImagePixelMap(const std::string &sourcePath)
340 {
341 MediaLibraryTracer tracer;
342 tracer.Start("SourceLoader CreateImagePixelMap");
343 uint32_t err = 0;
344 std::unique_ptr<ImageSource> imageSource = LoadImageSource(sourcePath, err);
345 if (err != E_OK || imageSource == nullptr) {
346 MEDIA_ERR_LOG("SourceLoader LoadImageSource error:%{public}d, errorno:%{public}d", err, errno);
347 return false;
348 }
349
350 ImageInfo imageInfo;
351 if (!IsSizeAcceptable(imageSource, imageInfo)) {
352 MEDIA_ERR_LOG("SourceLoader CreateImagePixelMap size not acceptable, status:%{public}s, path:%{public}s",
353 STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
354 return false;
355 }
356
357 Size targetSize = ConvertDecodeSize(data_, imageInfo.size, desiredSize_);
358 Size sourceSize = imageInfo.size;
359
360 // When encode picture, if mainPixel width or height is odd, hardware encode would fail.
361 // For the safety of encode process, only those of even desiredSize are allowed to generate througth picture.
362 bool shouldGeneratePicture = data_.loaderOpts.isHdr && imageSource->IsHdrImage() &&
363 data_.lcdDesiredSize.width % 2 == 0 && data_.lcdDesiredSize.height % 2 == 0;
364 bool isGenerateSucceed = shouldGeneratePicture ?
365 GeneratePictureSource(imageSource, targetSize) : GeneratePixelMapSource(imageSource, sourceSize, targetSize);
366 if (!isGenerateSucceed && shouldGeneratePicture) {
367 MEDIA_ERR_LOG("SourceLoader generate picture source failed, generate pixelmap instead, path:%{public}s",
368 DfxUtils::GetSafePath(data_.path).c_str());
369 std::unique_ptr<ImageSource> retryImageSource = LoadImageSource(sourcePath, err);
370 if (err != E_OK || retryImageSource == nullptr) {
371 MEDIA_ERR_LOG("LoadImageSource retryImageSource error:%{public}d, errorno:%{public}d", err, errno);
372 return false;
373 }
374 isGenerateSucceed = GeneratePixelMapSource(retryImageSource, sourceSize, targetSize);
375 }
376 if (!isGenerateSucceed) {
377 MEDIA_ERR_LOG("ImagePixelMap generate failed, path:%{public}s", DfxUtils::GetSafePath(data_.path).c_str());
378 return false;
379 }
380 tracer.Finish();
381
382 if (data_.orientation == 0) {
383 err = imageSource->GetImagePropertyInt(0, PHOTO_DATA_IMAGE_ORIENTATION, data_.orientation);
384 if (err != E_OK) {
385 MEDIA_ERR_LOG("SourceLoader Failed to get ImageProperty, path: %{public}s",
386 DfxUtils::GetSafePath(data_.path).c_str());
387 }
388 }
389
390 if (data_.mediaType == MEDIA_TYPE_VIDEO) {
391 data_.orientation = 0;
392 }
393 DfxManager::GetInstance()->HandleHighMemoryThumbnail(data_.path, MEDIA_TYPE_IMAGE, imageInfo.size.width,
394 imageInfo.size.height);
395 return true;
396 }
397
CreateSourcePixelMap()398 bool SourceLoader::CreateSourcePixelMap()
399 {
400 if (state_ == SourceState::LOCAL_ORIGIN && data_.mediaType == MEDIA_TYPE_VIDEO) {
401 return CreateVideoFramePixelMap();
402 }
403
404 if (GetSourcePath == nullptr) {
405 MEDIA_ERR_LOG("GetSourcePath is nullptr.");
406 return false;
407 }
408
409 std::string sourcePath = GetSourcePath(data_, error_);
410 if (sourcePath.empty()) {
411 MEDIA_ERR_LOG("SourceLoader source path unavailable, status:%{public}s, path:%{public}s",
412 STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
413 return false;
414 }
415 if (!CreateImagePixelMap(sourcePath)) {
416 MEDIA_ERR_LOG("SourceLoader fail to create image pixel map, status:%{public}s, path:%{public}s",
417 STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
418 return false;
419 }
420 return true;
421 }
422
RunLoading()423 bool SourceLoader::RunLoading()
424 {
425 if (data_.loaderOpts.loadingStates.empty()) {
426 MEDIA_ERR_LOG("source loading run loading failed, the given states is empty");
427 return false;
428 }
429 state_ = SourceState::BEGIN;
430 data_.source.ClearAllSource();
431 SetCurrentStateFunction();
432
433 // always check state not final after every state switch
434 while (!IsFinal()) {
435 SwitchToNextState(data_, state_);
436 MEDIA_DEBUG_LOG("SourceLoader new cycle status:%{public}s", STATE_NAME_MAP.at(state_).c_str());
437 if (IsFinal()) {
438 break;
439 }
440 SetCurrentStateFunction();
441 do {
442 if (state_ < SourceState::CLOUD_THUMB) {
443 data_.stats.sourceType = LoadSourceType::LOCAL_PHOTO;
444 } else if (state_ >= SourceState::CLOUD_THUMB && state_ <= SourceState::CLOUD_ORIGIN) {
445 data_.stats.sourceType = static_cast<LoadSourceType>(state_);
446 }
447
448 if (!CreateSourcePixelMap()) {
449 MEDIA_ERR_LOG("SourceLoader fail to create source pixel map, status:%{public}s, path:%{public}s",
450 STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
451 break;
452 }
453 state_ = SourceState::FINISH;
454 DfxManager::GetInstance()->HandleThumbnailGeneration(data_.stats);
455 } while (0);
456 };
457 if (state_ == SourceState::ERROR) {
458 data_.source.ClearAllSource();
459 }
460 if (data_.source.IsEmptySource()) {
461 MEDIA_ERR_LOG("SourceLoader source is nullptr, status:%{public}s, path:%{public}s",
462 STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
463 return false;
464 }
465 return true;
466 }
467
IsSizeAcceptable(std::unique_ptr<ImageSource> & imageSource,ImageInfo & imageInfo)468 bool SourceLoader::IsSizeAcceptable(std::unique_ptr<ImageSource>& imageSource, ImageInfo& imageInfo)
469 {
470 uint32_t err = imageSource->GetImageInfo(0, imageInfo);
471 if (err != E_OK) {
472 DfxManager::GetInstance()->HandleThumbnailError(data_.path, DfxType::IMAGE_SOURCE_GET_INFO, err);
473 error_ = E_ERR;
474 return false;
475 }
476
477 if (IsSizeLargeEnough == nullptr) {
478 MEDIA_ERR_LOG("IsSizeLargeEnough is nullptr.");
479 return false;
480 }
481
482 int32_t minSize = imageInfo.size.width < imageInfo.size.height ? imageInfo.size.width : imageInfo.size.height;
483 if (!IsSizeLargeEnough(data_, minSize)) {
484 MEDIA_DEBUG_LOG("SourceLoader size not acceptable, width:%{public}d, height:%{public}d", imageInfo.size.width,
485 imageInfo.size.height);
486 return false;
487 }
488
489 data_.stats.sourceWidth = imageInfo.size.width;
490 data_.stats.sourceHeight = imageInfo.size.height;
491 return true;
492 }
493
IsFinal()494 bool SourceLoader::IsFinal()
495 {
496 if (error_ != E_OK) {
497 state_ = SourceState::ERROR;
498 data_.stats.errorCode = error_;
499 return true;
500 }
501 if (state_ == SourceState::FINISH) {
502 return true;
503 }
504 return false;
505 }
506
GetSourcePath(ThumbnailData & data,int32_t & error)507 std::string LocalThumbSource::GetSourcePath(ThumbnailData &data, int32_t &error)
508 {
509 std::string tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
510 if (!IsLocalSourceAvailable(tmpPath)) {
511 return "";
512 }
513 return tmpPath;
514 }
515
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)516 bool LocalThumbSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
517 {
518 if (minSize < SHORT_SIDE_THRESHOLD) {
519 return false;
520 }
521 return true;
522 }
523
GetSourcePath(ThumbnailData & data,int32_t & error)524 std::string LocalLcdSource::GetSourcePath(ThumbnailData &data, int32_t &error)
525 {
526 std::string tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
527 if (!IsLocalSourceAvailable(tmpPath)) {
528 return "";
529 }
530 return tmpPath;
531 }
532
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)533 bool LocalLcdSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
534 {
535 if (minSize < SHORT_SIDE_THRESHOLD) {
536 return false;
537 }
538 return true;
539 }
540
GetSourcePath(ThumbnailData & data,int32_t & error)541 std::string LocalOriginSource::GetSourcePath(ThumbnailData &data, int32_t &error)
542 {
543 std::string tmpPath = GetLocalThumbnailPath(data.path, "");
544 if (!IsLocalSourceAvailable(tmpPath)) {
545 return "";
546 }
547 return tmpPath;
548 }
549
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)550 bool LocalOriginSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
551 {
552 return true;
553 }
554
GetSourcePath(ThumbnailData & data,int32_t & error)555 std::string CloudThumbSource::GetSourcePath(ThumbnailData &data, int32_t &error)
556 {
557 std::string tmpPath = GetThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
558 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
559 if (data.orientation != 0) {
560 return "";
561 }
562 int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
563 data.stats.openThumbCost = totalCost;
564 return tmpPath;
565 }
566
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)567 bool CloudThumbSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
568 {
569 if (minSize < SHORT_SIDE_THRESHOLD) {
570 return false;
571 }
572 return true;
573 }
574
GetSourcePath(ThumbnailData & data,int32_t & error)575 std::string CloudLcdSource::GetSourcePath(ThumbnailData &data, int32_t &error)
576 {
577 std::string tmpPath;
578 if (data.orientation != 0) {
579 tmpPath = GetLcdExPath(data.path);
580 } else {
581 tmpPath = GetThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
582 }
583 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
584 if (!IsCloudSourceAvailable(tmpPath)) {
585 return "";
586 }
587 int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
588 data.stats.openLcdCost = totalCost;
589 return tmpPath;
590 }
591
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)592 bool CloudLcdSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
593 {
594 if (data.mediaType == MEDIA_TYPE_VIDEO) {
595 return true;
596 }
597 int photoShorterSide = data.photoWidth < data.photoHeight ? data.photoWidth : data.photoHeight;
598 if (photoShorterSide != 0 && photoShorterSide < SHORT_SIDE_THRESHOLD) {
599 return true;
600 }
601 if (minSize < SHORT_SIDE_THRESHOLD) {
602 return false;
603 }
604 return true;
605 }
606
GetSourcePath(ThumbnailData & data,int32_t & error)607 std::string CloudOriginSource::GetSourcePath(ThumbnailData &data, int32_t &error)
608 {
609 if (data.mediaType == MEDIA_TYPE_VIDEO) {
610 // avoid opening cloud origin video file.
611 MEDIA_ERR_LOG("avoid opening cloud origin video file path:%{public}s",
612 DfxUtils::GetSafePath(data.path).c_str());
613 return "";
614 }
615 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
616 if (!IsCloudSourceAvailable(data.path)) {
617 return "";
618 }
619 int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
620 data.stats.openOriginCost = totalCost;
621 return data.path;
622 }
623
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)624 bool CloudOriginSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
625 {
626 return true;
627 }
628
629 } // namespace Media
630 } // namespace OHOS