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