• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "cover_position_parser.h"
17 
18 #include <fcntl.h>
19 
20 #include "dfx_utils.h"
21 #include "directory_ex.h"
22 #include "ffrt_inner.h"
23 #include "media_column.h"
24 #include "medialibrary_notify.h"
25 #include "medialibrary_unistore_manager.h"
26 #include "moving_photo_file_utils.h"
27 #include "unique_fd.h"
28 #include "userfile_manager_types.h"
29 
30 namespace OHOS {
31 namespace Media {
32 using namespace std;
33 using namespace OHOS::NativeRdb;
34 
35 const int32_t MAX_TASK_NUM = 100;
36 
GetInstance()37 CoverPositionParser &CoverPositionParser::GetInstance()
38 {
39     static CoverPositionParser instance_;
40     return instance_;
41 }
42 
AddTask(const string & path,const string & fileUri)43 bool CoverPositionParser::AddTask(const string &path, const string &fileUri)
44 {
45     lock_guard<mutex> lock(mtx_);
46     if (tasks_.size() >= MAX_TASK_NUM) {
47         MEDIA_INFO_LOG("The max queue length has been reached, ignore current task: %{public}s",
48                        DfxUtils::GetSafePath(path).c_str());
49         return false;
50     }
51     tasks_.push(make_pair(path, fileUri));
52     if (tasks_.size() == 1 && !processing_) {
53         MEDIA_DEBUG_LOG("queue has task, start process");
54         processing_ = true;
55         StartTask();
56     }
57     return true;
58 }
59 
StartTask()60 void CoverPositionParser::StartTask()
61 {
62     ffrt::submit([this]() { ProcessCoverPosition(); });
63 }
64 
ProcessCoverPosition()65 void CoverPositionParser::ProcessCoverPosition()
66 {
67     bool hasTask = true;
68     while (hasTask) {
69         pair<string, string> task = GetNextTask();
70         if (task.first.empty()) {
71             hasTask = false;
72             continue;
73         }
74         UpdateCoverPosition(task.first);
75         SendUpdateNotify(task.second);
76     }
77 }
78 
GetNextTask()79 pair<string, string> CoverPositionParser::GetNextTask()
80 {
81     lock_guard<mutex> lock(mtx_);
82     if (tasks_.empty()) {
83         MEDIA_DEBUG_LOG("queue is empty, stop process");
84         processing_ = false;
85         return make_pair("", "");
86     }
87     pair<string, string> task = tasks_.front();
88     tasks_.pop();
89     return task;
90 }
91 
UpdateCoverPosition(const string & path)92 void CoverPositionParser::UpdateCoverPosition(const string &path)
93 {
94     string extraDataPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(path);
95     string absExtraDataPath;
96     if (!PathToRealPath(extraDataPath, absExtraDataPath)) {
97         MEDIA_ERR_LOG("realpath fail: %{public}s, errno: %{public}d", DfxUtils::GetSafePath(extraDataPath).c_str(),
98                       errno);
99         return;
100     }
101 
102     uint64_t coverPosition = 0;
103     uint32_t version = 0;
104     uint32_t frameIndex = 0;
105     bool hasCinemagraphInfo = false;
106     UniqueFd extraDataFd(open(absExtraDataPath.c_str(), O_RDONLY));
107     (void)MovingPhotoFileUtils::GetVersionAndFrameNum(extraDataFd.Get(), version, frameIndex, hasCinemagraphInfo);
108     if (frameIndex != 0) {
109         string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(path);
110         (void)MovingPhotoFileUtils::GetCoverPosition(videoPath, frameIndex, coverPosition);
111     }
112 
113     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
114     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "rdbStore is nullptr!");
115 
116     AbsRdbPredicates predicates = AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
117     predicates.EqualTo(PhotoColumn::MEDIA_FILE_PATH, path);
118     ValuesBucket values;
119     values.PutLong(PhotoColumn::PHOTO_COVER_POSITION, coverPosition);
120     values.PutInt(PhotoColumn::PHOTO_IS_RECTIFICATION_COVER, 1);
121 
122     int32_t changeRows = -1;
123     int32_t ret = rdbStore->Update(changeRows, values, predicates);
124     CHECK_AND_PRINT_LOG(ret == E_OK, "execute update cover_position failed, ret = %{public}d", ret);
125 }
126 
SendUpdateNotify(const string & fileUri)127 void CoverPositionParser::SendUpdateNotify(const string &fileUri)
128 {
129     auto watch = MediaLibraryNotify::GetInstance();
130     if (watch == nullptr) {
131         MEDIA_ERR_LOG("Can not get MediaLibraryNotify, fail to send new asset notify.");
132         return;
133     }
134     watch->Notify(fileUri, NotifyType::NOTIFY_UPDATE);
135 }
136 } // namespace Media
137 } // namespace OHOS