1 /*
2 * Copyright (C) 2025 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 #define MLOG_TAG "MediaLibraryCloneRestoreCVAnalysis"
17
18 #include "clone_restore_cv_analysis.h"
19
20 #include "backup_database_utils.h"
21 #include "backup_file_utils.h"
22 #include "media_file_utils.h"
23 #include "media_log.h"
24 #include "upgrade_restore_task_report.h"
25
26 namespace OHOS::Media {
27 const int32_t PAGE_SIZE = 200;
28 const std::vector<std::string> EFFECTLINE_ID = { "fileId", "prefileId" };
29 const std::vector<std::string> EFFECTLINE_URI = { "fileUri", "prefileUri" };
30 const std::string EFFECTLINE_TYPE_HITCHCOCK = "TYPE_HITCHCOCK";
31 const std::string EFFECTLINE_TYPE_UAV = "TYPE_UAV";
32 const std::string EFFECTLINE_TYPE_HILIGHT_SLOW = "TYPE_HILIGHT_SLOW";
33 const std::string EFFECTLINE_TYPE_HILIGHT_CLIP = "TYPE_HILIGHT_CLIP";
34 const std::string EFFECTLINE_TYPE_MASK1 = "TYPE_MASK1";
35 const std::string EFFECTLINE_TYPE_MASK2 = "TYPE_MASK2";
36 const std::string HIGHLIGHT_ASSET_URI_PREFIX = "file://media/highlight/video/";
37 const std::string HIGHLIGHT_ASSET_URI_SUFFIX = "?oper=highlight";
38 const std::string PHOTO_URI_PREFIX = "file://media/Photo/";
39 const std::string GARBLE_DST_PATH = "/storage/media/local/files";
40 const std::string RESTORE_STATUS_SUCCESS = "1";
41
42 template<typename Key, typename Value>
GetValueFromMap(const std::unordered_map<Key,Value> & map,const Key & key,const Value & defaultValue=Value ())43 Value GetValueFromMap(const std::unordered_map<Key, Value> &map, const Key &key, const Value &defaultValue = Value())
44 {
45 auto it = map.find(key);
46 CHECK_AND_RETURN_RET(it != map.end(), defaultValue);
47 return it->second;
48 }
49
Init(int32_t sceneCode,const std::string & taskId,std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb,std::shared_ptr<NativeRdb::RdbStore> mediaRdb,const std::string & backupRestoreDir)50 void CloneRestoreCVAnalysis::Init(int32_t sceneCode, const std::string &taskId,
51 std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb,
52 std::shared_ptr<NativeRdb::RdbStore> mediaRdb, const std::string &backupRestoreDir)
53 {
54 sceneCode_ = sceneCode;
55 taskId_ = taskId;
56 mediaLibraryRdb_ = mediaLibraryRdb;
57 mediaRdb_ = mediaRdb;
58
59 assetPath_ = backupRestoreDir + "/storage/media/local/files/highlight/video/";
60 isHighlightVideoDirExist_ = MediaFileUtils::IsDirectory(assetPath_);
61 MEDIA_INFO_LOG("/highlight/video/ source dir %{public}s.", isHighlightVideoDirExist_ ? "exist" : "don't exist");
62 garblePath_ = backupRestoreDir + GARBLE_DST_PATH;
63 }
64
RestoreAlbums(CloneRestoreHighlight & cloneHighlight)65 void CloneRestoreCVAnalysis::RestoreAlbums(CloneRestoreHighlight &cloneHighlight)
66 {
67 CHECK_AND_RETURN_LOG(mediaRdb_ != nullptr && mediaLibraryRdb_ != nullptr, "rdbStore is nullptr.");
68 CHECK_AND_RETURN_LOG(cloneHighlight.IsCloneHighlight(), "clone highlight flag is false.");
69
70 MEDIA_INFO_LOG("restore highlight cv analysis album start.");
71 int64_t startRestoreAssetSdTime = MediaFileUtils::UTCTimeMilliSeconds();
72 RestoreAssetSdMap(cloneHighlight);
73 int64_t startRestoreAlbumAssetTime = MediaFileUtils::UTCTimeMilliSeconds();
74 RestoreAlbumAssetMap(cloneHighlight);
75 int64_t startUpdatePlayInfoTime = MediaFileUtils::UTCTimeMilliSeconds();
76 std::vector<int32_t> updateHighlightIds;
77 UpdateHighlightPlayInfos(cloneHighlight, updateHighlightIds);
78 cloneHighlight.UpdateHighlightStatus(updateHighlightIds);
79 int64_t endTime = MediaFileUtils::UTCTimeMilliSeconds();
80 MEDIA_INFO_LOG("TimeCost: RestoreAlbums: %{public}" PRId64 ", RestoreAssetSdMap: %{public}" PRId64
81 ", RestoreAlbumAssetMap: %{public}" PRId64 ", UpdateHighlightPlayInfos: %{public}" PRId64,
82 endTime - startRestoreAssetSdTime, startRestoreAlbumAssetTime - startRestoreAssetSdTime,
83 startUpdatePlayInfoTime - startRestoreAlbumAssetTime, endTime - startUpdatePlayInfoTime);
84 restoreTimeCost_ += endTime - startRestoreAssetSdTime;
85 cloneHighlight.UpdateRestoreTimeCost(restoreTimeCost_);
86 ReportCloneRestoreCVAnalysisTask();
87 }
88
RestoreAssetSdMap(CloneRestoreHighlight & cloneHighlight)89 void CloneRestoreCVAnalysis::RestoreAssetSdMap(CloneRestoreHighlight &cloneHighlight)
90 {
91 const std::string QUERY_SQL = "SELECT * FROM tab_analysis_asset_sd_map LIMIT ?, ?";
92 int32_t rowCount = 0;
93 int32_t offset = 0;
94 do {
95 std::vector<NativeRdb::ValuesBucket> values;
96 std::vector<NativeRdb::ValueObject> params = {offset, PAGE_SIZE};
97 auto resultSet = BackupDatabaseUtils::QuerySql(mediaRdb_, QUERY_SQL, params);
98 CHECK_AND_BREAK_ERR_LOG(resultSet != nullptr, "resultSet is nullptr");
99 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
100 int32_t oldFileId = GetInt32Val("map_asset_source", resultSet);
101 int32_t oldAssetId = GetInt32Val("map_asset_destination", resultSet);
102 NativeRdb::ValuesBucket value;
103 value.PutInt("map_asset_source", cloneHighlight.GetNewHighlightPhotoId(oldFileId));
104 value.PutInt("map_asset_destination", cloneHighlight.GetNewHighlightPhotoId(oldAssetId));
105 values.emplace_back(value);
106 }
107 resultSet->GetRowCount(rowCount);
108 offset += PAGE_SIZE;
109 resultSet->Close();
110 InsertIntoAssetSdMap(values);
111 } while (rowCount == PAGE_SIZE);
112 }
113
RestoreAlbumAssetMap(CloneRestoreHighlight & cloneHighlight)114 void CloneRestoreCVAnalysis::RestoreAlbumAssetMap(CloneRestoreHighlight &cloneHighlight)
115 {
116 const std::string QUERY_SQL = "SELECT tab_analysis_album_asset_map.* FROM tab_analysis_album_asset_map "
117 " INNER JOIN tab_highlight_album AS h ON tab_analysis_album_asset_map.map_album = h.id "
118 " WHERE h.highlight_status > 0 LIMIT ?, ?";
119 int32_t rowCount = 0;
120 int32_t offset = 0;
121 do {
122 std::vector<NativeRdb::ValuesBucket> values;
123 std::vector<NativeRdb::ValueObject> params = {offset, PAGE_SIZE};
124 auto resultSet = BackupDatabaseUtils::QuerySql(mediaRdb_, QUERY_SQL, params);
125 CHECK_AND_BREAK_ERR_LOG(resultSet != nullptr, "resultSet is nullptr");
126 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
127 int32_t oldAlbumId = GetInt32Val("map_album", resultSet);
128 int32_t oldAssetId = GetInt32Val("map_asset", resultSet);
129 NativeRdb::ValuesBucket value;
130 value.PutInt("map_album", cloneHighlight.GetNewHighlightAlbumId(oldAlbumId));
131 value.PutInt("map_asset", cloneHighlight.GetNewHighlightPhotoId(oldAssetId));
132 values.emplace_back(value);
133 }
134 resultSet->GetRowCount(rowCount);
135 offset += PAGE_SIZE;
136 resultSet->Close();
137 InsertIntoAlbumAssetMap(values);
138 } while (rowCount == PAGE_SIZE);
139 }
140
InsertIntoAssetSdMap(std::vector<NativeRdb::ValuesBucket> & values)141 void CloneRestoreCVAnalysis::InsertIntoAssetSdMap(std::vector<NativeRdb::ValuesBucket> &values)
142 {
143 int64_t rowNum = 0;
144 int32_t errCode = BatchInsertWithRetry("tab_analysis_asset_sd_map", values, rowNum);
145 assetSdSuccessCnt_ += rowNum;
146 CHECK_AND_RETURN(errCode != E_OK || rowNum != static_cast<int64_t>(values.size()));
147 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
148 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
149 "insert into sdMap fail, num:" + std::to_string(failNums));
150 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
151 assetSdFailedCnt_ += failNums;
152 }
153
InsertIntoAlbumAssetMap(std::vector<NativeRdb::ValuesBucket> & values)154 void CloneRestoreCVAnalysis::InsertIntoAlbumAssetMap(std::vector<NativeRdb::ValuesBucket> &values)
155 {
156 int64_t rowNum = 0;
157 int32_t errCode = BatchInsertWithRetry("tab_analysis_album_asset_map", values, rowNum);
158 albumAssetSuccessCnt_ += rowNum;
159 CHECK_AND_RETURN(errCode != E_OK || rowNum != static_cast<int64_t>(values.size()));
160 int64_t failNums = static_cast<int64_t>(values.size()) - rowNum;
161 ErrorInfo errorInfo(RestoreError::INSERT_FAILED, 0, std::to_string(errCode),
162 "insert into AssetMap fail, num:" + std::to_string(failNums));
163 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
164 albumAssetFailedCnt_ += failNums;
165 }
166
BatchInsertWithRetry(const std::string & tableName,const std::vector<NativeRdb::ValuesBucket> & values,int64_t & rowNum)167 int32_t CloneRestoreCVAnalysis::BatchInsertWithRetry(const std::string &tableName,
168 const std::vector<NativeRdb::ValuesBucket> &values, int64_t &rowNum)
169 {
170 CHECK_AND_RETURN_RET(!values.empty(), 0);
171 int32_t errCode = E_ERR;
172 TransactionOperations trans{ __func__ };
173 trans.SetBackupRdbStore(mediaLibraryRdb_);
174 std::function<int(void)> func = [&]()->int {
175 errCode = trans.BatchInsert(rowNum, tableName, values);
176 CHECK_AND_PRINT_LOG(errCode == E_OK,
177 "InsertSql failed, errCode: %{public}d, rowNum: %{public}" PRId64, errCode, rowNum);
178 return errCode;
179 };
180 errCode = trans.RetryTrans(func, true);
181 CHECK_AND_PRINT_LOG(errCode == E_OK, "BatchInsertWithRetry: tans finish fail!, ret:%{public}d", errCode);
182 return errCode;
183 }
184
ParsePlayInfo(const std::string & oldPlayInfo,CloneRestoreHighlight & cloneHighlight)185 std::string CloneRestoreCVAnalysis::ParsePlayInfo(const std::string &oldPlayInfo, CloneRestoreHighlight &cloneHighlight)
186 {
187 nlohmann::json newPlayInfo = nlohmann::json::parse(oldPlayInfo, nullptr, false);
188 CHECK_AND_RETURN_RET_LOG(!newPlayInfo.is_discarded(), cloneHighlight.GetDefaultPlayInfo(),
189 "parse json string failed.");
190 if (newPlayInfo["effectline"].contains("effectline")) {
191 for (size_t effectlineIndex = 0; effectlineIndex < newPlayInfo["effectline"]["effectline"].size();
192 effectlineIndex++) {
193 ParseEffectline(newPlayInfo, effectlineIndex, cloneHighlight);
194 }
195 }
196 if (newPlayInfo.contains("timeline")) {
197 for (size_t timelineIndex = 0; timelineIndex < newPlayInfo["timeline"].size(); timelineIndex++) {
198 ParseTimeline(newPlayInfo, timelineIndex, cloneHighlight);
199 }
200 }
201 return newPlayInfo.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
202 }
203
ParseEffectline(nlohmann::json & newPlayInfo,size_t effectlineIndex,CloneRestoreHighlight & cloneHighlight)204 void CloneRestoreCVAnalysis::ParseEffectline(nlohmann::json &newPlayInfo, size_t effectlineIndex,
205 CloneRestoreHighlight &cloneHighlight)
206 {
207 if (newPlayInfo["effectline"]["effectline"][effectlineIndex].contains("effectVideoUri")) {
208 std::string oldEffectVideoUri = newPlayInfo["effectline"]["effectline"][effectlineIndex]["effectVideoUri"];
209 if (MediaFileUtils::StartsWith(oldEffectVideoUri, PHOTO_URI_PREFIX)) {
210 newPlayInfo["effectline"]["effectline"][effectlineIndex]["effectVideoUri"] =
211 GetNewPhotoUriByUri(oldEffectVideoUri, cloneHighlight);
212 } else if (MediaFileUtils::StartsWith(oldEffectVideoUri, HIGHLIGHT_ASSET_URI_PREFIX)) {
213 newPlayInfo["effectline"]["effectline"][effectlineIndex]["effectVideoUri"] =
214 GetNewEffectVideoUri(oldEffectVideoUri, cloneHighlight);
215 }
216 }
217
218 bool cond = newPlayInfo["effectline"]["effectline"][effectlineIndex].contains("effect") &&
219 newPlayInfo["effectline"]["effectline"][effectlineIndex]["effect"] == EFFECTLINE_TYPE_MASK2 &&
220 newPlayInfo["effectline"]["effectline"][effectlineIndex].contains("transitionVideoUri");
221 if (cond) {
222 std::string transVideoUri = GetNewTransitionVideoUri(
223 newPlayInfo["effectline"]["effectline"][effectlineIndex]["transitionVideoUri"], cloneHighlight);
224 newPlayInfo["effectline"]["effectline"][effectlineIndex]["transitionVideoUri"] = transVideoUri;
225
226 cond = (effectlineIndex > 0 &&
227 newPlayInfo["effectline"]["effectline"][effectlineIndex - 1].contains("effect") &&
228 newPlayInfo["effectline"]["effectline"][effectlineIndex - 1]["effect"] == EFFECTLINE_TYPE_MASK1 &&
229 newPlayInfo["effectline"]["effectline"][effectlineIndex - 1].contains("transitionVideoUri"));
230 CHECK_AND_EXECUTE(!cond,
231 newPlayInfo["effectline"]["effectline"][effectlineIndex - 1]["transitionVideoUri"] = transVideoUri);
232 }
233
234 ParseEffectlineFileData(newPlayInfo, effectlineIndex, cloneHighlight);
235 }
236
ParseEffectlineFileData(nlohmann::json & newPlayInfo,size_t effectlineIndex,CloneRestoreHighlight & cloneHighlight)237 void CloneRestoreCVAnalysis::ParseEffectlineFileData(nlohmann::json &newPlayInfo, size_t effectlineIndex,
238 CloneRestoreHighlight &cloneHighlight)
239 {
240 for (size_t infoIndex = 0; infoIndex < EFFECTLINE_ID.size(); infoIndex++) {
241 if (newPlayInfo["effectline"]["effectline"][effectlineIndex].contains(EFFECTLINE_ID[infoIndex])) {
242 for (size_t idIndex = 0;
243 idIndex < newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_ID[infoIndex]].size();
244 idIndex++) {
245 int32_t oldFileId =
246 newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_ID[infoIndex]][idIndex];
247 newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_ID[infoIndex]][idIndex] =
248 cloneHighlight.GetNewHighlightPhotoId(oldFileId);
249 }
250 }
251
252 if (newPlayInfo["effectline"]["effectline"][effectlineIndex].contains(EFFECTLINE_URI[infoIndex])) {
253 for (size_t uriIndex = 0;
254 uriIndex < newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_URI[infoIndex]].size();
255 uriIndex++) {
256 std::string oldFileUri =
257 newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_URI[infoIndex]][uriIndex];
258 newPlayInfo["effectline"]["effectline"][effectlineIndex][EFFECTLINE_URI[infoIndex]][uriIndex] =
259 GetNewPhotoUriByUri(oldFileUri, cloneHighlight);
260 }
261 }
262 }
263 }
264
ParseTimeline(nlohmann::json & newPlayInfo,size_t timelineIndex,CloneRestoreHighlight & cloneHighlight)265 void CloneRestoreCVAnalysis::ParseTimeline(nlohmann::json &newPlayInfo, size_t timelineIndex,
266 CloneRestoreHighlight &cloneHighlight)
267 {
268 if (newPlayInfo["timeline"][timelineIndex].contains("effectVideoUri")) {
269 std::string oldEffectVideoUri = newPlayInfo["timeline"][timelineIndex]["effectVideoUri"];
270 newPlayInfo["timeline"][timelineIndex]["effectVideoUri"] = GetValueFromMap(assetUriMap_, oldEffectVideoUri);
271 }
272
273 if (newPlayInfo["timeline"][timelineIndex].contains("transitionVideoUri")) {
274 std::string oldTransVideoUri = newPlayInfo["timeline"][timelineIndex]["transitionVideoUri"];
275 newPlayInfo["timeline"][timelineIndex]["transitionVideoUri"] = GetValueFromMap(assetUriMap_, oldTransVideoUri);
276 }
277
278 if (newPlayInfo["timeline"][timelineIndex].contains("fileId")) {
279 for (size_t idIndex = 0; idIndex < newPlayInfo["timeline"][timelineIndex]["fileId"].size(); idIndex++) {
280 int32_t oldFileId = newPlayInfo["timeline"][timelineIndex]["fileId"][idIndex];
281 newPlayInfo["timeline"][timelineIndex]["fileId"][idIndex] =
282 cloneHighlight.GetNewHighlightPhotoId(oldFileId);
283 }
284 }
285
286 if (newPlayInfo["timeline"][timelineIndex].contains("fileUri")) {
287 for (size_t uriIndex = 0; uriIndex < newPlayInfo["timeline"][timelineIndex]["fileUri"].size(); uriIndex++) {
288 std::string oldFileUri = newPlayInfo["timeline"][timelineIndex]["fileUri"][uriIndex];
289 newPlayInfo["timeline"][timelineIndex]["fileUri"][uriIndex] =
290 GetNewPhotoUriByUri(oldFileUri, cloneHighlight);
291 }
292 }
293 }
294
GetNewEffectVideoUri(const std::string & oldVideoUri,CloneRestoreHighlight & cloneHighlight)295 std::string CloneRestoreCVAnalysis::GetNewEffectVideoUri(const std::string &oldVideoUri,
296 CloneRestoreHighlight &cloneHighlight)
297 {
298 CHECK_AND_RETURN_RET(assetUriMap_.find(oldVideoUri) == assetUriMap_.end(), assetUriMap_.at(oldVideoUri));
299 CHECK_AND_RETURN_RET(oldVideoUri != "", "");
300 size_t rightIndex = oldVideoUri.rfind("/");
301 CHECK_AND_RETURN_RET(rightIndex != std::string::npos && rightIndex > 0, "");
302 size_t leftIndex = oldVideoUri.rfind("/", rightIndex - 1);
303 CHECK_AND_RETURN_RET(leftIndex != std::string::npos && rightIndex > leftIndex + 1, "");
304 int32_t oldAssetId = std::atoi((oldVideoUri.substr(leftIndex + 1, rightIndex - leftIndex - 1)).c_str());
305 int32_t newAssetId = cloneHighlight.GetNewHighlightPhotoId(oldAssetId);
306
307 size_t suffixLeftIndex = oldVideoUri.find("_", rightIndex);
308 CHECK_AND_RETURN_RET(suffixLeftIndex != std::string::npos, "");
309 size_t suffixRightIndex = oldVideoUri.find("?", suffixLeftIndex);
310 CHECK_AND_RETURN_RET(suffixRightIndex != std::string::npos && suffixRightIndex > suffixLeftIndex, "");
311 std::string suffix = oldVideoUri.substr(suffixLeftIndex, suffixRightIndex - suffixLeftIndex);
312 std::string newVideoUri = HIGHLIGHT_ASSET_URI_PREFIX + std::to_string(newAssetId)
313 + "/" + std::to_string(newAssetId) + suffix + HIGHLIGHT_ASSET_URI_SUFFIX;
314
315 assetUriMap_.insert(std::make_pair(oldVideoUri, newVideoUri));
316 std::string dstPath = "/storage/media/local/files/highlight/video/" + std::to_string(newAssetId) + "/" +
317 std::to_string(newAssetId) + suffix;
318 std::string srcPath = assetPath_ + std::to_string(oldAssetId) + "/" + std::to_string(oldAssetId) + suffix;
319 MoveAnalysisAssets(srcPath, dstPath);
320 return newVideoUri;
321 }
322
GetNewTransitionVideoUri(const std::string & oldVideoUri,CloneRestoreHighlight & cloneHighlight)323 std::string CloneRestoreCVAnalysis::GetNewTransitionVideoUri(const std::string &oldVideoUri,
324 CloneRestoreHighlight &cloneHighlight)
325 {
326 CHECK_AND_RETURN_RET(assetUriMap_.find(oldVideoUri) == assetUriMap_.end(), assetUriMap_.at(oldVideoUri));
327 CHECK_AND_RETURN_RET(oldVideoUri != "", "");
328 size_t rightIndex = oldVideoUri.rfind("/");
329 CHECK_AND_RETURN_RET(rightIndex != std::string::npos && rightIndex > 0, "");
330 size_t leftIndex = oldVideoUri.rfind("/", rightIndex - 1);
331 CHECK_AND_RETURN_RET(leftIndex != std::string::npos && rightIndex > leftIndex + 1, "");
332 int32_t oldAssetId = std::atoi((oldVideoUri.substr(leftIndex + 1, rightIndex - leftIndex - 1)).c_str());
333 int32_t newAssetId = cloneHighlight.GetNewHighlightPhotoId(oldAssetId);
334
335 size_t secondLeftIndex = oldVideoUri.find("_", rightIndex);
336 CHECK_AND_RETURN_RET(secondLeftIndex != std::string::npos, "");
337 size_t secondRightIndex = oldVideoUri.find("_", secondLeftIndex + 1);
338 CHECK_AND_RETURN_RET(secondRightIndex != std::string::npos && secondRightIndex > secondLeftIndex + 1, "");
339 int32_t oldNextAssetId = std::atoi((oldVideoUri.substr(secondLeftIndex + 1,
340 secondRightIndex - secondLeftIndex - 1)).c_str());
341 int32_t newNextPhotoId = cloneHighlight.GetNewHighlightPhotoId(oldNextAssetId);
342
343 size_t suffixRightIndex = oldVideoUri.find("?", secondRightIndex);
344 CHECK_AND_RETURN_RET(suffixRightIndex != std::string::npos && suffixRightIndex > secondRightIndex, "");
345 std::string suffix = oldVideoUri.substr(secondRightIndex, suffixRightIndex - secondRightIndex);
346
347 std::string newVideoUri = HIGHLIGHT_ASSET_URI_PREFIX + std::to_string(newAssetId) + "/" +
348 std::to_string(newAssetId) + "_" + std::to_string(newNextPhotoId) + suffix + HIGHLIGHT_ASSET_URI_SUFFIX;
349 assetUriMap_.insert(std::make_pair(oldVideoUri, newVideoUri));
350
351 std::string dstPath = "/storage/media/local/files/highlight/video/" + std::to_string(newAssetId) + "/" +
352 std::to_string(newAssetId) + "_" + std::to_string(newNextPhotoId) + suffix;
353 std::string srcPath = assetPath_ + std::to_string(oldAssetId) + "/" +
354 std::to_string(oldAssetId) + "_" + std::to_string(oldNextAssetId) + suffix;
355 MoveAnalysisAssets(srcPath, dstPath);
356 return newVideoUri;
357 }
358
GetNewPhotoUriByUri(const std::string & oldUri,CloneRestoreHighlight & cloneHighlight)359 std::string CloneRestoreCVAnalysis::GetNewPhotoUriByUri(const std::string &oldUri,
360 CloneRestoreHighlight &cloneHighlight)
361 {
362 CHECK_AND_RETURN_RET(assetUriMap_.find(oldUri) == assetUriMap_.end(), assetUriMap_.at(oldUri));
363 CHECK_AND_RETURN_RET(oldUri != "", "");
364 size_t rightIndex = oldUri.rfind("/");
365 CHECK_AND_RETURN_RET(rightIndex != std::string::npos && rightIndex > 0, "");
366 size_t suffixIndex = oldUri.find("?", rightIndex);
367 rightIndex = oldUri.rfind("/", rightIndex - 1);
368 CHECK_AND_RETURN_RET(rightIndex != std::string::npos && rightIndex > 0, "");
369 size_t leftIndex = oldUri.rfind("/", rightIndex - 1);
370 CHECK_AND_RETURN_RET(leftIndex != std::string::npos && rightIndex > leftIndex + 1, "");
371
372 int32_t oldPhotoId = std::atoi((oldUri.substr(leftIndex + 1, rightIndex - leftIndex - 1)).c_str());
373 std::string newUri = cloneHighlight.GetNewHighlightPhotoUri(oldPhotoId);
374
375 CHECK_AND_EXECUTE(suffixIndex == std::string::npos, newUri += oldUri.substr(suffixIndex));
376 assetUriMap_.insert(std::make_pair(oldUri, newUri));
377 return newUri;
378 }
379
MoveAnalysisAssets(const std::string & srcPath,const std::string & dstPath)380 void CloneRestoreCVAnalysis::MoveAnalysisAssets(const std::string &srcPath, const std::string &dstPath)
381 {
382 std::string srcGarble = srcPath;
383 srcGarble.replace(0, assetPath_.length(), "*/");
384 std::string dstGarble = MediaFileUtils::DesensitizePath(dstPath);
385 CHECK_AND_RETURN_LOG(MediaFileUtils::IsFileExists(srcPath), "src file doesn't exist, srcPath:%{public}s."
386 "dstPath:%{public}s", srcGarble.c_str(), dstGarble.c_str());
387 CHECK_AND_RETURN_INFO_LOG(!MediaFileUtils::IsFileExists(dstPath),
388 "dst file already exists, srcPath:%{public}s, dstPath:%{public}s.", srcGarble.c_str(), dstGarble.c_str());
389 int32_t errCode = BackupFileUtils::PreparePath(dstPath);
390 CHECK_AND_RETURN_LOG(errCode == E_OK, "PreparePath failed, can't move file, srcPath:%{public}s, "
391 "dstPath:%{public}s, errcode:%{public}d", srcGarble.c_str(), dstGarble.c_str(), errCode);
392 errCode = BackupFileUtils::MoveFile(srcPath, dstPath, sceneCode_);
393 CHECK_AND_RETURN_LOG(errCode == E_OK, "move file failed, srcPath:%{public}s, dstPath:%{public}s, "
394 "errcode:%{public}d", srcGarble.c_str(), dstGarble.c_str(), errCode);
395 MEDIA_INFO_LOG("move file successed, srcPath:%{public}s, dstPath:%{public}s", srcGarble.c_str(), dstGarble.c_str());
396 }
397
UpdateHighlightPlayInfos(CloneRestoreHighlight & cloneHighlight,std::vector<int32_t> & updateHighlightIds)398 void CloneRestoreCVAnalysis::UpdateHighlightPlayInfos(CloneRestoreHighlight &cloneHighlight,
399 std::vector<int32_t> &updateHighlightIds)
400 {
401 int32_t rowCount = 0;
402 int32_t offset = 0;
403 std::string defaultPlayInfo = cloneHighlight.GetDefaultPlayInfo();
404 do {
405 const std::string QUERY_SQL = "SELECT p.album_id, p.play_info_id, p.play_info FROM tab_highlight_play_info AS p"
406 " INNER JOIN tab_highlight_album AS h ON p.album_id = h.id WHERE h.highlight_status > 0 "
407 " LIMIT " + std::to_string(offset) + ", " + std::to_string(PAGE_SIZE);
408 auto resultSet = BackupDatabaseUtils::GetQueryResultSet(mediaRdb_, QUERY_SQL);
409 CHECK_AND_RETURN_INFO_LOG(resultSet != nullptr, "query resultSql is null.");
410
411 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
412 std::optional<int32_t> oldAlbumId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "p.album_id");
413 CHECK_AND_CONTINUE(oldAlbumId.has_value());
414 std::optional<int32_t> playId = BackupDatabaseUtils::GetOptionalValue<int32_t>(resultSet, "p.play_info_id");
415 std::optional<std::string> oldPlayInfo =
416 BackupDatabaseUtils::GetOptionalValue<std::string>(resultSet, "p.play_info");
417 std::string newPlayInfo = defaultPlayInfo;
418 CHECK_AND_EXECUTE(!oldPlayInfo.has_value(),
419 newPlayInfo = ParsePlayInfo(oldPlayInfo.value(), cloneHighlight));
420
421 int32_t albumId = cloneHighlight.GetNewHighlightAlbumId(oldAlbumId.value());
422 std::string updatePlayInfoSql = "UPDATE tab_highlight_play_info SET play_info = ? WHERE album_id = ? ";
423 int32_t ret = E_ERR;
424 if (playId.has_value()) {
425 std::string playInfoId = std::to_string(playId.value());
426 updatePlayInfoSql += "AND play_info_id = ?";
427 ret = BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, updatePlayInfoSql,
428 { newPlayInfo, albumId, playInfoId });
429 } else {
430 updatePlayInfoSql += "AND play_info_id ISNULL";
431 ret = BackupDatabaseUtils::ExecuteSQL(mediaLibraryRdb_, updatePlayInfoSql,
432 { newPlayInfo, albumId });
433 }
434 bool successfulParseCond = (newPlayInfo != defaultPlayInfo && ret == E_OK) ||
435 (newPlayInfo == defaultPlayInfo && oldPlayInfo == defaultPlayInfo);
436 if (successfulParseCond) {
437 updateHighlightIds.emplace_back(albumId);
438 continue;
439 }
440 CHECK_AND_PRINT_LOG(ret == E_OK, "Update play_info Sql err, highlight id: %{public}d, errCode: %{public}d",
441 albumId, ret);
442 ErrorInfo errorInfo(RestoreError::UPDATE_FAILED, 0, std::to_string(ret),
443 "Update play_info failed. highlight id:" + std::to_string(albumId));
444 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_).ReportError(errorInfo);
445 }
446 resultSet->GetRowCount(rowCount);
447 offset += PAGE_SIZE;
448 resultSet->Close();
449 } while (rowCount == PAGE_SIZE);
450 }
451
ReportCloneRestoreCVAnalysisTask()452 void CloneRestoreCVAnalysis::ReportCloneRestoreCVAnalysisTask()
453 {
454 std::stringstream totalReport;
455 totalReport << "isHighlightVideoDirExist: " << isHighlightVideoDirExist_ << ", timeCost: " << restoreTimeCost_ <<
456 "; ASSET_SD: success: " << assetSdSuccessCnt_ << ", failed: " << assetSdFailedCnt_ <<
457 "; ALBUM_ASSET: success: " << albumAssetSuccessCnt_ << ", failed: " << albumAssetFailedCnt_;
458 UpgradeRestoreTaskReport().SetSceneCode(sceneCode_).SetTaskId(taskId_)
459 .Report("CLONE_RESTORE_CV_ANALYSIS_TOTAL", RESTORE_STATUS_SUCCESS, totalReport.str());
460 }
461 } // namespace OHOS::Media