• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     int fd = open(absFilePath.c_str(), O_RDONLY);
142     if (fd < 0) {
143         MEDIA_ERR_LOG("open cloud file fail: errno: %{public}d, %{public}s",
144             errno, DfxUtils::GetSafePath(path).c_str());
145         return false;
146     }
147     close(fd);
148     return true;
149 }
150 
NeedAutoResize(const Size & size)151 bool NeedAutoResize(const Size &size)
152 {
153     // Only small thumbnails need to be scaled after decoding, others should resized while decoding.
154     return size.width > SHORT_SIDE_THRESHOLD && size.height > SHORT_SIDE_THRESHOLD;
155 }
156 
GenDecodeOpts(const Size & sourceSize,const Size & targetSize,DecodeOptions & decodeOpts)157 bool GenDecodeOpts(const Size &sourceSize, const Size &targetSize, DecodeOptions &decodeOpts)
158 {
159     if (targetSize.width == 0) {
160         MEDIA_ERR_LOG("Failed to generate decodeOpts, scale size contains zero");
161         return false;
162     }
163     decodeOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
164     if (NeedAutoResize(targetSize)) {
165         decodeOpts.desiredSize = targetSize;
166         return true;
167     }
168 
169     int32_t decodeScale = 1;
170     int32_t scaleFactor = sourceSize.width / targetSize.width;
171     while (scaleFactor /= DECODE_SCALE_BASE) {
172         decodeScale *= DECODE_SCALE_BASE;
173     }
174     decodeOpts.desiredSize = {
175         std::ceil(sourceSize.width / decodeScale),
176         std::ceil(sourceSize.height / decodeScale),
177     };
178     return true;
179 }
180 
ConvertDecodeSize(ThumbnailData & data,const Size & sourceSize,Size & desiredSize)181 Size ConvertDecodeSize(ThumbnailData &data, const Size &sourceSize, Size &desiredSize)
182 {
183     int width = sourceSize.width;
184     int height = sourceSize.height;
185     if (!ThumbnailUtils::ResizeThumb(width, height)) {
186         MEDIA_ERR_LOG("ResizeThumb failed");
187         return {0, 0};
188     }
189     Size thumbDesiredSize = {width, height};
190     data.thumbDesiredSize = thumbDesiredSize;
191     float desiredScale = static_cast<float>(thumbDesiredSize.height) / static_cast<float>(thumbDesiredSize.width);
192     float sourceScale = static_cast<float>(sourceSize.height) / static_cast<float>(sourceSize.width);
193     float scale = 1.0f;
194     if (sourceScale - desiredScale <= EPSILON) {
195         scale = (float)thumbDesiredSize.height / sourceSize.height;
196     } else {
197         scale = (float)thumbDesiredSize.width / sourceSize.width;
198     }
199     scale = scale < 1.0f ? scale : 1.0f;
200     Size thumbDecodeSize = {
201         static_cast<int32_t> (scale * sourceSize.width),
202         static_cast<int32_t> (scale * sourceSize.height),
203     };
204 
205     width = sourceSize.width;
206     height = sourceSize.height;
207     if (!ThumbnailUtils::ResizeLcd(width, height)) {
208         MEDIA_ERR_LOG("ResizeLcd failed");
209         return {0, 0};
210     }
211     Size lcdDesiredSize = {width, height};
212     data.lcdDesiredSize = lcdDesiredSize;
213 
214     int lcdMinSide = std::min(lcdDesiredSize.width, lcdDesiredSize.height);
215     int thumbMinSide = std::min(thumbDesiredSize.width, thumbDesiredSize.height);
216     Size lcdDecodeSize = lcdMinSide < thumbMinSide ? thumbDecodeSize : lcdDesiredSize;
217 
218     if (data.loaderOpts.decodeInThumbSize) {
219         desiredSize = thumbDesiredSize;
220         return thumbDecodeSize;
221     } else if (data.needResizeLcd) {
222         desiredSize = lcdDesiredSize;
223         return lcdDecodeSize;
224     } else {
225         desiredSize = lcdDesiredSize;
226         return lcdDesiredSize;
227     }
228 }
229 
SwitchToNextState(ThumbnailData & data,SourceState & state)230 void SwitchToNextState(ThumbnailData &data, SourceState &state)
231 {
232     if (state == SourceState::FINISH) {
233         MEDIA_INFO_LOG("SwitchToNextState current state is FINISH.");
234         return;
235     }
236     auto iter = data.loaderOpts.loadingStates.find(state);
237     if (iter == data.loaderOpts.loadingStates.end()) {
238         MEDIA_WARN_LOG("SwitchToNextState find next state error, current state:%{public}d",
239             static_cast<int32_t>(state));
240         return;
241     }
242     state = iter->second;
243 }
244 
LoadImageSource(const std::string & path,uint32_t & err)245 unique_ptr<ImageSource> LoadImageSource(const std::string &path, uint32_t &err)
246 {
247     MediaLibraryTracer tracer;
248     tracer.Start("LoadImageSource");
249 
250     SourceOptions opts;
251     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, err);
252     if (err != E_OK || !imageSource) {
253         MEDIA_ERR_LOG("Failed to LoadImageSource, pixelmap path: %{public}s exists: %{public}d",
254             path.c_str(), MediaFileUtils::IsFileExists(path));
255         DfxManager::GetInstance()->HandleThumbnailError(path, DfxType::IMAGE_SOURCE_CREATE, err);
256         return imageSource;
257     }
258     return imageSource;
259 }
260 
CreateVideoFramePixelMap()261 bool SourceLoader::CreateVideoFramePixelMap()
262 {
263     MediaLibraryTracer tracer;
264     tracer.Start("CreateVideoFramePixelMap");
265     return ThumbnailUtils::LoadVideoFile(data_, desiredSize_);
266 }
267 
SetCurrentStateFunction()268 void SourceLoader::SetCurrentStateFunction()
269 {
270     StateFunc stateFunc = STATE_FUNC_MAP.at(state_);
271     GetSourcePath = stateFunc.GetSourcePath;
272     IsSizeLargeEnough = stateFunc.IsSizeLargeEnough;
273 }
274 
CreateImagePixelMap(const std::string & sourcePath)275 bool SourceLoader::CreateImagePixelMap(const std::string &sourcePath)
276 {
277     MediaLibraryTracer tracer;
278     tracer.Start("SourceLoader CreateImagePixelMap");
279     uint32_t err = 0;
280     std::unique_ptr<ImageSource> imageSource = LoadImageSource(sourcePath, err);
281     if (err != E_OK || imageSource == nullptr) {
282         MEDIA_ERR_LOG("SourceLoader LoadImageSource error:%{public}d, errorno:%{public}d", err, errno);
283         return false;
284     }
285 
286     ImageInfo imageInfo;
287     if (!IsSizeAcceptable(imageSource, imageInfo)) {
288         MEDIA_ERR_LOG("SourceLoader CreateImagePixelMap size not acceptable, status:%{public}s, path:%{public}s",
289             STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
290         return false;
291     }
292     DecodeOptions decodeOpts;
293     if (data_.loaderOpts.isHdr && imageSource->IsHdrImage()) {
294         decodeOpts.desiredDynamicRange = DecodeDynamicRange::HDR;
295     }
296     Size targetSize = ConvertDecodeSize(data_, imageInfo.size, desiredSize_);
297     if (!GenDecodeOpts(imageInfo.size, targetSize, decodeOpts)) {
298         MEDIA_ERR_LOG("SourceLoader failed to generate decodeOpts, pixelmap path %{public}s",
299             DfxUtils::GetSafePath(data_.path).c_str());
300         return false;
301     }
302     data_.source = imageSource->CreatePixelMap(decodeOpts, err);
303     if ((err != E_OK) || (data_.source == nullptr)) {
304         DfxManager::GetInstance()->HandleThumbnailError(data_.path, DfxType::IMAGE_SOURCE_CREATE_PIXELMAP, err);
305         return false;
306     }
307     if (!NeedAutoResize(targetSize) && !ThumbnailUtils::ScaleTargetPixelMap(data_.source, targetSize,
308         Media::AntiAliasingOption::HIGH)) {
309         MEDIA_ERR_LOG("SourceLoader fail to scaleTarget, path %{public}s", DfxUtils::GetSafePath(data_.path).c_str());
310         return false;
311     }
312     tracer.Finish();
313 
314     if (data_.orientation == 0) {
315         err = imageSource->GetImagePropertyInt(0, PHOTO_DATA_IMAGE_ORIENTATION, data_.orientation);
316         if (err != E_OK) {
317             MEDIA_ERR_LOG("SourceLoader Failed to get ImageProperty, path: %{public}s",
318                 DfxUtils::GetSafePath(data_.path).c_str());
319         }
320     }
321 
322     if (data_.mediaType == MEDIA_TYPE_VIDEO) {
323         data_.orientation = 0;
324     }
325     DfxManager::GetInstance()->HandleHighMemoryThumbnail(data_.path, MEDIA_TYPE_IMAGE, imageInfo.size.width,
326         imageInfo.size.height);
327     return true;
328 }
329 
CreateSourcePixelMap()330 bool SourceLoader::CreateSourcePixelMap()
331 {
332     if (state_ == SourceState::LOCAL_ORIGIN && data_.mediaType == MEDIA_TYPE_VIDEO) {
333         return CreateVideoFramePixelMap();
334     }
335 
336     if (GetSourcePath == nullptr) {
337         MEDIA_ERR_LOG("GetSourcePath is nullptr.");
338         return false;
339     }
340 
341     std::string sourcePath = GetSourcePath(data_, error_);
342     if (sourcePath.empty()) {
343         MEDIA_ERR_LOG("SourceLoader source path unavailable, status:%{public}s, path:%{public}s",
344             STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
345         return false;
346     }
347     if (!CreateImagePixelMap(sourcePath)) {
348         MEDIA_ERR_LOG("SourceLoader fail to create image pixel map, status:%{public}s, path:%{public}s",
349             STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
350         return false;
351     }
352     return true;
353 }
354 
RunLoading()355 bool SourceLoader::RunLoading()
356 {
357     if (data_.loaderOpts.loadingStates.empty()) {
358         MEDIA_ERR_LOG("source loading run loading failed, the given states is empty");
359         return false;
360     }
361     state_ = SourceState::BEGIN;
362     data_.source = nullptr;
363     SetCurrentStateFunction();
364 
365     // always check state not final after every state switch
366     while (!IsFinal()) {
367         SwitchToNextState(data_, state_);
368         MEDIA_DEBUG_LOG("SourceLoader new cycle status:%{public}s", STATE_NAME_MAP.at(state_).c_str());
369         if (IsFinal()) {
370             break;
371         }
372         SetCurrentStateFunction();
373         do {
374             if (state_ < SourceState::CLOUD_THUMB) {
375                 data_.stats.sourceType = LoadSourceType::LOCAL_PHOTO;
376             } else if (state_ >= SourceState::CLOUD_THUMB && state_ <= SourceState::CLOUD_ORIGIN) {
377                 data_.stats.sourceType = static_cast<LoadSourceType>(state_);
378             }
379 
380             if (!CreateSourcePixelMap()) {
381                 MEDIA_ERR_LOG("SourceLoader fail to create source pixel map, status:%{public}s, path:%{public}s",
382                     STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
383                 break;
384             }
385             state_ = SourceState::FINISH;
386             DfxManager::GetInstance()->HandleThumbnailGeneration(data_.stats);
387         } while (0);
388     };
389     if (state_ == SourceState::ERROR) {
390         data_.source = nullptr;
391     }
392     if (data_.source == nullptr) {
393         MEDIA_ERR_LOG("SourceLoader source is nullptr, status:%{public}s, path:%{public}s",
394             STATE_NAME_MAP.at(state_).c_str(), DfxUtils::GetSafePath(data_.path).c_str());
395         return false;
396     }
397     return true;
398 }
399 
IsSizeAcceptable(std::unique_ptr<ImageSource> & imageSource,ImageInfo & imageInfo)400 bool SourceLoader::IsSizeAcceptable(std::unique_ptr<ImageSource>& imageSource, ImageInfo& imageInfo)
401 {
402     uint32_t err = imageSource->GetImageInfo(0, imageInfo);
403     if (err != E_OK) {
404         DfxManager::GetInstance()->HandleThumbnailError(data_.path, DfxType::IMAGE_SOURCE_GET_INFO, err);
405         error_ = E_ERR;
406         return false;
407     }
408 
409     if (IsSizeLargeEnough == nullptr) {
410         MEDIA_ERR_LOG("IsSizeLargeEnough is nullptr.");
411         return false;
412     }
413 
414     int32_t minSize = imageInfo.size.width < imageInfo.size.height ? imageInfo.size.width : imageInfo.size.height;
415     if (!IsSizeLargeEnough(data_, minSize)) {
416         MEDIA_DEBUG_LOG("SourceLoader size not acceptable, width:%{public}d, height:%{public}d", imageInfo.size.width,
417             imageInfo.size.height);
418         return false;
419     }
420 
421     data_.stats.sourceWidth = imageInfo.size.width;
422     data_.stats.sourceHeight = imageInfo.size.height;
423     return true;
424 }
425 
IsFinal()426 bool SourceLoader::IsFinal()
427 {
428     if (error_ != E_OK) {
429         state_ = SourceState::ERROR;
430         data_.stats.errorCode = error_;
431         return true;
432     }
433     if (state_ == SourceState::FINISH) {
434         return true;
435     }
436     return false;
437 }
438 
GetSourcePath(ThumbnailData & data,int32_t & error)439 std::string LocalThumbSource::GetSourcePath(ThumbnailData &data, int32_t &error)
440 {
441     std::string tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
442     if (!IsLocalSourceAvailable(tmpPath)) {
443         return "";
444     }
445     return tmpPath;
446 }
447 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)448 bool LocalThumbSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
449 {
450     if (minSize < SHORT_SIDE_THRESHOLD) {
451         return false;
452     }
453     return true;
454 }
455 
GetSourcePath(ThumbnailData & data,int32_t & error)456 std::string LocalLcdSource::GetSourcePath(ThumbnailData &data, int32_t &error)
457 {
458     std::string tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
459     if (!IsLocalSourceAvailable(tmpPath)) {
460         return "";
461     }
462     return tmpPath;
463 }
464 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)465 bool LocalLcdSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
466 {
467     if (minSize < SHORT_SIDE_THRESHOLD) {
468         return false;
469     }
470     return true;
471 }
472 
GetSourcePath(ThumbnailData & data,int32_t & error)473 std::string LocalOriginSource::GetSourcePath(ThumbnailData &data, int32_t &error)
474 {
475     std::string tmpPath = GetLocalThumbnailPath(data.path, "");
476     if (!IsLocalSourceAvailable(tmpPath)) {
477         return "";
478     }
479     return tmpPath;
480 }
481 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)482 bool LocalOriginSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
483 {
484     return true;
485 }
486 
GetSourcePath(ThumbnailData & data,int32_t & error)487 std::string CloudThumbSource::GetSourcePath(ThumbnailData &data, int32_t &error)
488 {
489     std::string tmpPath = GetThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
490     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
491     if (data.orientation != 0) {
492         return "";
493     }
494     int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
495     data.stats.openThumbCost = totalCost;
496     return tmpPath;
497 }
498 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)499 bool CloudThumbSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
500 {
501     if (minSize < SHORT_SIDE_THRESHOLD) {
502         return false;
503     }
504     return true;
505 }
506 
GetSourcePath(ThumbnailData & data,int32_t & error)507 std::string CloudLcdSource::GetSourcePath(ThumbnailData &data, int32_t &error)
508 {
509     std::string tmpPath;
510     if (data.orientation != 0) {
511         tmpPath = GetLcdExPath(data.path);
512     } else {
513         tmpPath = GetThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
514     }
515     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
516     if (!IsCloudSourceAvailable(tmpPath)) {
517         return "";
518     }
519     int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
520     data.stats.openLcdCost = totalCost;
521     return tmpPath;
522 }
523 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)524 bool CloudLcdSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
525 {
526     if (data.mediaType == MEDIA_TYPE_VIDEO) {
527         return true;
528     }
529     int photoShorterSide = data.photoWidth < data.photoHeight ? data.photoWidth : data.photoHeight;
530     if (photoShorterSide != 0 && photoShorterSide < SHORT_SIDE_THRESHOLD) {
531         return true;
532     }
533     if (minSize < SHORT_SIDE_THRESHOLD) {
534         return false;
535     }
536     return true;
537 }
538 
GetSourcePath(ThumbnailData & data,int32_t & error)539 std::string CloudOriginSource::GetSourcePath(ThumbnailData &data, int32_t &error)
540 {
541     if (data.mediaType == MEDIA_TYPE_VIDEO) {
542         // avoid opening cloud origin video file.
543         MEDIA_ERR_LOG("avoid opening cloud origin video file path:%{public}s",
544             DfxUtils::GetSafePath(data.path).c_str());
545         return "";
546     }
547     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
548     if (!IsCloudSourceAvailable(data.path)) {
549         return "";
550     }
551     int32_t totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - startTime);
552     data.stats.openOriginCost = totalCost;
553     return data.path;
554 }
555 
IsSizeLargeEnough(ThumbnailData & data,int32_t & minSize)556 bool CloudOriginSource::IsSizeLargeEnough(ThumbnailData &data, int32_t &minSize)
557 {
558     return true;
559 }
560 
561 } // namespace Media
562 } // namespace OHOS