1 /*
2  * Copyright (c) 2023-2023 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 "deferred_video_controller.h"
17 
18 #include "dp_power_manager.h"
19 #include "dp_timer.h"
20 
21 namespace OHOS {
22 namespace CameraStandard {
23 namespace DeferredProcessing {
24 class DeferredVideoController::StateListener : public IVideoStateChangeListener {
25 public:
StateListener(const std::weak_ptr<DeferredVideoController> & controller)26     explicit StateListener(const std::weak_ptr<DeferredVideoController>& controller) : controller_(controller)
27     {
28         DP_DEBUG_LOG("entered.");
29     }
30 
~StateListener()31     ~StateListener() override
32     {
33         DP_DEBUG_LOG("entered.");
34     }
35 
OnSchedulerChanged(const ScheduleType & type,const ScheduleInfo & scheduleInfo)36     void OnSchedulerChanged(const ScheduleType& type, const ScheduleInfo& scheduleInfo) override
37     {
38         auto controller = controller_.lock();
39         DP_CHECK_ERROR_RETURN_LOG(controller == nullptr, "video controller is nullptr.");
40         controller->OnSchedulerChanged(type, scheduleInfo);
41     }
42 
43 private:
44     std::weak_ptr<DeferredVideoController> controller_;
45 };
46 
47 class DeferredVideoController::VideoJobRepositoryListener : public IVideoJobRepositoryListener {
48 public:
VideoJobRepositoryListener(const std::weak_ptr<DeferredVideoController> & controller)49     explicit VideoJobRepositoryListener(const std::weak_ptr<DeferredVideoController>& controller)
50         : controller_(controller)
51     {
52         DP_DEBUG_LOG("entered.");
53     }
54 
~VideoJobRepositoryListener()55     ~VideoJobRepositoryListener()
56     {
57         DP_DEBUG_LOG("entered.");
58     }
59 
OnVideoJobChanged(const DeferredVideoJobPtr & jobPtr)60     void OnVideoJobChanged(const DeferredVideoJobPtr& jobPtr) override
61     {
62         auto controller = controller_.lock();
63         DP_CHECK_ERROR_RETURN_LOG(controller == nullptr, "video controller is nullptr.");
64         controller->OnVideoJobChanged(jobPtr);
65     }
66 
67 private:
68     std::weak_ptr<DeferredVideoController> controller_;
69 };
70 
DeferredVideoController(const int32_t userId,std::shared_ptr<VideoJobRepository> repository,std::shared_ptr<DeferredVideoProcessor> processor)71 DeferredVideoController::DeferredVideoController(const int32_t userId, std::shared_ptr<VideoJobRepository> repository,
72     std::shared_ptr<DeferredVideoProcessor> processor)
73     : userId_(userId),
74       videoProcessor_(processor),
75       videoJobRepository_(repository)
76 {
77     DP_DEBUG_LOG("entered, userid: %{public}d", userId_);
78 }
79 
~DeferredVideoController()80 DeferredVideoController::~DeferredVideoController()
81 {
82     DP_DEBUG_LOG("entered.");
83     videoProcessor_ = nullptr;
84     videoJobRepository_ = nullptr;
85     videoStrategyCenter_ = nullptr;
86     videoStateChangeListener_ = nullptr;
87     videoJobChangeListener_ = nullptr;
88     StopSuspendLock();
89 }
90 
Initialize()91 void DeferredVideoController::Initialize()
92 {
93     DP_DEBUG_LOG("entered.");
94     videoJobChangeListener_ = std::make_shared<VideoJobRepositoryListener>(weak_from_this());
95     videoJobRepository_->RegisterJobListener(videoJobChangeListener_);
96     videoStrategyCenter_ = CreateShared<VideoStrategyCenter>(userId_, videoJobRepository_);
97 
98     videoStrategyCenter_->Initialize();
99     videoStateChangeListener_ = std::make_shared<StateListener>(weak_from_this());
100     videoStrategyCenter_->RegisterStateChangeListener(videoStateChangeListener_);
101 }
102 
HandleServiceDied()103 void DeferredVideoController::HandleServiceDied()
104 {
105     DP_DEBUG_LOG("entered.");
106     std::vector<std::string> errorTasks;
107     videoJobRepository_->GetRunningJobList(errorTasks);
108     if (!errorTasks.empty()) {
109         StopSuspendLock();
110     }
111 }
112 
HandleSuccess(const int32_t userId,const DeferredVideoWorkPtr & work)113 void DeferredVideoController::HandleSuccess(const int32_t userId, const DeferredVideoWorkPtr& work)
114 {
115     auto videoId = work->GetDeferredVideoJob()->GetVideoId();
116     auto out = work->GetDeferredVideoJob()->GetOutputFd();
117     DP_INFO_LOG("handle success, videoId: %{public}s, outFd: %{public}d", videoId.c_str(), out->GetFd());
118     HandleNormalSchedule(work);
119     videoProcessor_->OnProcessDone(userId, videoId, out);
120 }
121 
HandleError(const int32_t userId,const DeferredVideoWorkPtr & work,DpsError errorCode)122 void DeferredVideoController::HandleError(const int32_t userId, const DeferredVideoWorkPtr& work, DpsError errorCode)
123 {
124     auto videoId = work->GetDeferredVideoJob()->GetVideoId();
125     DP_INFO_LOG("handle error videoId: %{public}s", videoId.c_str());
126     if (errorCode == DpsError::DPS_ERROR_VIDEO_PROC_INTERRUPTED) {
127         StopSuspendLock();
128     }
129     HandleNormalSchedule(work);
130     videoProcessor_->OnError(userId, videoId, errorCode);
131 }
132 
OnVideoJobChanged(const DeferredVideoJobPtr & jobPtr)133 void DeferredVideoController::OnVideoJobChanged(const DeferredVideoJobPtr& jobPtr)
134 {
135     DP_INFO_LOG("entered, videoId: %{public}s", jobPtr->GetVideoId().c_str());
136     TryDoSchedule();
137 }
138 
OnSchedulerChanged(const ScheduleType & type,const ScheduleInfo & scheduleInfo)139 void DeferredVideoController::OnSchedulerChanged(const ScheduleType& type, const ScheduleInfo& scheduleInfo)
140 {
141     DP_INFO_LOG("video schedule isNeedStop: %{public}d, isCharging: %{public}d",
142         scheduleInfo.isNeedStop, scheduleInfo.isCharging);
143     if (scheduleInfo.isNeedStop) {
144         PauseRequests(type);
145     } else {
146         TryDoSchedule();
147     }
148 }
149 
TryDoSchedule()150 void DeferredVideoController::TryDoSchedule()
151 {
152     DP_DEBUG_LOG("entered.");
153     std::lock_guard<std::recursive_mutex> lock(mutex_);
154     auto work = videoStrategyCenter_->GetWork();
155     DP_INFO_LOG("strategy get work: %{public}d", work != nullptr);
156     if (work == nullptr) {
157         StopSuspendLock();
158         return;
159     }
160 
161     DP_CHECK_EXECUTE(work->IsSuspend(), StartSuspendLock());
162     PostProcess(work);
163 }
164 
PauseRequests(const ScheduleType & type)165 void DeferredVideoController::PauseRequests(const ScheduleType& type)
166 {
167     DP_CHECK_RETURN(videoJobRepository_->GetRunningJobCounts() == 0);
168     videoProcessor_->PauseRequest(type);
169 }
170 
PostProcess(const DeferredVideoWorkPtr & work)171 void DeferredVideoController::PostProcess(const DeferredVideoWorkPtr& work)
172 {
173     DP_DEBUG_LOG("entered");
174     videoProcessor_->PostProcess(work);
175 }
176 
SetDefaultExecutionMode()177 void DeferredVideoController::SetDefaultExecutionMode()
178 {
179     DP_DEBUG_LOG("entered");
180     videoProcessor_->SetDefaultExecutionMode();
181 }
182 
StartSuspendLock()183 void DeferredVideoController::StartSuspendLock()
184 {
185     DP_CHECK_RETURN(normalTimeId_ != INVALID_TIMEID);
186     uint32_t processTime = static_cast<uint32_t>(
187         std::min(videoStrategyCenter_->GetAvailableTime(), ONCE_PROCESS_TIME));
188     normalTimeId_ = DpsTimer::GetInstance().StartTimer([&]() {OnTimerOut();}, processTime);
189     DPSProwerManager::GetInstance().SetAutoSuspend(false, processTime + DELAY_TIME);
190     DP_INFO_LOG("DpsTimer start: normal schedule timeId: %{public}d, processTime: %{public}d.",
191         static_cast<int32_t>(normalTimeId_), processTime);
192 }
193 
StopSuspendLock()194 void DeferredVideoController::StopSuspendLock()
195 {
196     DPSProwerManager::GetInstance().SetAutoSuspend(true);
197     DP_CHECK_RETURN(normalTimeId_ == INVALID_TIMEID);
198     DP_INFO_LOG("DpsTimer stop: normal schedule timeId: %{public}d.", normalTimeId_);
199     DpsTimer::GetInstance().StopTimer(normalTimeId_);
200 }
201 
HandleNormalSchedule(const DeferredVideoWorkPtr & work)202 void DeferredVideoController::HandleNormalSchedule(const DeferredVideoWorkPtr& work)
203 {
204     DP_CHECK_RETURN(!work->IsSuspend());
205 
206     DP_DEBUG_LOG("handle normal schedule videoId: %{public}s", work->GetDeferredVideoJob()->GetVideoId().c_str());
207     auto usedTime = static_cast<int32_t>(work->GetExecutionTime());
208     videoStrategyCenter_->UpdateAvailableTime(false, usedTime);
209 }
210 
OnTimerOut()211 void DeferredVideoController::OnTimerOut()
212 {
213     DP_INFO_LOG("DpsTimer executed: normal schedule time out.");
214     normalTimeId_ = INVALID_TIMEID;
215     videoStrategyCenter_->UpdateSingleTime(false);
216     PauseRequests(NORMAL_TIME_STATE);
217 }
218 } // namespace DeferredProcessing
219 } // namespace CameraStandard
220 } // namespace OHOS