1 /*
2 * Copyright (C) 2021 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 "player_server_task_mgr.h"
17 #include "media_log.h"
18 #include "media_errors.h"
19 #include "qos.h"
20
21 using namespace OHOS::QOS;
22
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "PlayerServerTaskMgr" };
25 }
26
27 namespace OHOS {
28 namespace Media {
PlayerServerTaskMgr()29 PlayerServerTaskMgr::PlayerServerTaskMgr()
30 {
31 MEDIA_LOGD("enter ctor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
32 }
33
~PlayerServerTaskMgr()34 PlayerServerTaskMgr::~PlayerServerTaskMgr()
35 {
36 MEDIA_LOGD("enter dtor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
37 (void)Reset();
38 }
39
Init()40 int32_t PlayerServerTaskMgr::Init()
41 {
42 std::unique_lock<std::mutex> lock(mutex_);
43 if (isInited_) {
44 return MSERR_OK;
45 }
46
47 taskThread_ = std::make_unique<TaskQueue>("PlayerEngine");
48 int32_t ret = taskThread_->Start();
49 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "task thread start failed");
50 isInited_ = true;
51
52 return MSERR_OK;
53 }
54
EnqueueTask(const std::shared_ptr<ITaskHandler> & task,PlayerServerTaskType type,const std::string & taskName)55 int32_t PlayerServerTaskMgr::EnqueueTask(const std::shared_ptr<ITaskHandler> &task, PlayerServerTaskType type,
56 const std::string &taskName)
57 {
58 (void)taskThread_->EnqueueTask(task);
59 currTwoPhaseTask_ = task;
60 currTwoPhaseType_ = type;
61 currTwoPhaseTaskName_ = taskName;
62 if (taskName.compare("volume") == 0) {
63 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] start",
64 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str());
65 } else {
66 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] start",
67 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str());
68 }
69
70 return MSERR_OK;
71 }
72
LaunchTask(const std::shared_ptr<ITaskHandler> & task,PlayerServerTaskType type,const std::string & taskName,const std::shared_ptr<ITaskHandler> & cancelTask)73 int32_t PlayerServerTaskMgr::LaunchTask(const std::shared_ptr<ITaskHandler> &task, PlayerServerTaskType type,
74 const std::string &taskName, const std::shared_ptr<ITaskHandler> &cancelTask)
75 {
76 std::unique_lock<std::mutex> lock(mutex_);
77 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
78
79 if (taskName == "play" || taskName == "prepare") {
80 taskThread_->SetQos(QosLevel::QOS_USER_INTERACTIVE);
81 } else if (taskName == "pause") {
82 taskThread_->ResetQos();
83 }
84
85 (void)cancelTask;
86 if (type != PlayerServerTaskType::STATE_CHANGE && type != PlayerServerTaskType::LIGHT_TASK) {
87 return MSERR_OK;
88 }
89 if (currTwoPhaseTask_ == nullptr) {
90 return EnqueueTask(task, type, taskName);
91 }
92
93 if (taskName.compare("volume") == 0) {
94 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
95 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
96 } else {
97 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
98 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
99 }
100
101 pendingTwoPhaseTasks_.push_back({ type, task, nullptr, taskName });
102 return MSERR_OK;
103 }
104
SpeedTask(const std::shared_ptr<ITaskHandler> & task,const std::shared_ptr<ITaskHandler> & cancelTask,const std::string & taskName,int32_t speedMode)105 int32_t PlayerServerTaskMgr::SpeedTask(const std::shared_ptr<ITaskHandler> &task,
106 const std::shared_ptr<ITaskHandler> &cancelTask,
107 const std::string &taskName, int32_t speedMode)
108 {
109 std::unique_lock<std::mutex> lock(mutex_);
110 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
111 if (currTwoPhaseTask_ == nullptr) {
112 EnqueueTask(task, PlayerServerTaskType::RATE_CHANGE, taskName);
113 MEDIA_LOGI("speed task[%{public}s] start", currTwoPhaseTaskName_.c_str());
114 return MSERR_OK;
115 }
116 MEDIA_LOGI("current task[%{public}s] is in processing, new task[%{public}s] wait",
117 currTwoPhaseTaskName_.c_str(), taskName.c_str());
118 for (auto &item : pendingTwoPhaseTasks_) {
119 if (item.type == PlayerServerTaskType::RATE_CHANGE &&
120 item.speedMode_ != speedMode) {
121 item.type = PlayerServerTaskType::CANCEL_TASK;
122 MEDIA_LOGI("replace old speed task");
123 }
124 }
125
126 pendingTwoPhaseTasks_.push_back({
127 PlayerServerTaskType::RATE_CHANGE, task, cancelTask, taskName, -1, -1, speedMode
128 });
129 return MSERR_OK;
130 }
131
EnqueueSeekTask(const std::shared_ptr<ITaskHandler> & task,PlayerServerTaskType type,const std::string & taskName,int32_t seekMode,int32_t seekTime)132 int32_t PlayerServerTaskMgr::EnqueueSeekTask(const std::shared_ptr<ITaskHandler> &task,
133 PlayerServerTaskType type, const std::string &taskName, int32_t seekMode, int32_t seekTime)
134 {
135 (void)taskThread_->EnqueueTask(task);
136 currTwoPhaseTask_ = task;
137 currTwoPhaseType_ = type;
138 currTwoPhaseTaskName_ = taskName;
139 currentSeekMode_ = seekMode;
140 currentSeekTime_ = seekTime;
141 MEDIA_LOGI("0x%{public}06" PRIXPTR " seek task[%{public}s] start",
142 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str());
143 return MSERR_OK;
144 }
145
SeekTask(const std::shared_ptr<ITaskHandler> & task,const std::shared_ptr<ITaskHandler> & cancelTask,const std::string & taskName,int32_t seekMode,int32_t seekTime)146 int32_t PlayerServerTaskMgr::SeekTask(const std::shared_ptr<ITaskHandler> &task,
147 const std::shared_ptr<ITaskHandler> &cancelTask,
148 const std::string &taskName, int32_t seekMode, int32_t seekTime)
149 {
150 std::unique_lock<std::mutex> lock(mutex_);
151 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
152
153 if (currTwoPhaseTask_ == nullptr) {
154 return EnqueueSeekTask(task, PlayerServerTaskType::SEEKING, taskName, seekMode, seekTime);
155 }
156 MEDIA_LOGI("current task[%{public}s] is in processing, new task[%{public}s] wait",
157 currTwoPhaseTaskName_.c_str(), taskName.c_str());
158 for (auto &item : pendingTwoPhaseTasks_) {
159 if (item.type == PlayerServerTaskType::SEEKING) {
160 item.type = PlayerServerTaskType::CANCEL_TASK;
161 MEDIA_LOGI("replace old seek task");
162 }
163 }
164
165 if (currentSeekMode_ == seekMode && currentSeekTime_ == seekTime) {
166 pendingTwoPhaseTasks_.push_back({
167 PlayerServerTaskType::CANCEL_TASK, task, cancelTask, taskName, seekMode, seekTime
168 });
169 MEDIA_LOGI("abandon old seek task");
170 } else {
171 pendingTwoPhaseTasks_.push_back({
172 PlayerServerTaskType::SEEKING, task, cancelTask, taskName, seekMode, seekTime
173 });
174 }
175 return MSERR_OK;
176 }
177
FreezeTask(const std::shared_ptr<ITaskHandler> & task,const std::shared_ptr<ITaskHandler> & cancelTask,const std::string & taskName)178 int32_t PlayerServerTaskMgr::FreezeTask(const std::shared_ptr<ITaskHandler> &task,
179 const std::shared_ptr<ITaskHandler> &cancelTask, const std::string &taskName)
180 {
181 std::unique_lock<std::mutex> lock(mutex_);
182 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
183
184 if (currTwoPhaseTask_ == nullptr) {
185 return EnqueueTask(task, PlayerServerTaskType::FREEZE_TASK, taskName);
186 }
187 MEDIA_LOGI("current task[%{public}s] is in processing, new task[%{public}s] wait",
188 currTwoPhaseTaskName_.c_str(), taskName.c_str());
189
190 pendingTwoPhaseTasks_.push_back({
191 PlayerServerTaskType::FREEZE_TASK, task, cancelTask, taskName
192 });
193 return MSERR_OK;
194 }
195
UnFreezeTask(const std::shared_ptr<ITaskHandler> & task,const std::shared_ptr<ITaskHandler> & cancelTask,const std::string & taskName)196 int32_t PlayerServerTaskMgr::UnFreezeTask(const std::shared_ptr<ITaskHandler> &task,
197 const std::shared_ptr<ITaskHandler> &cancelTask, const std::string &taskName)
198 {
199 std::unique_lock<std::mutex> lock(mutex_);
200 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
201
202 if (currTwoPhaseTask_ == nullptr) {
203 return EnqueueTask(task, PlayerServerTaskType::UNFREEZE_TASK, taskName);
204 }
205 MEDIA_LOGI("current task[%{public}s] is in processing, new task[%{public}s] wait",
206 currTwoPhaseTaskName_.c_str(), taskName.c_str());
207
208 pendingTwoPhaseTasks_.push_back({
209 PlayerServerTaskType::UNFREEZE_TASK, task, cancelTask, taskName
210 });
211 return MSERR_OK;
212 }
213
SeekContinousTask(const std::shared_ptr<ITaskHandler> & task,const std::string & taskName)214 int32_t PlayerServerTaskMgr::SeekContinousTask(const std::shared_ptr<ITaskHandler> &task, const std::string &taskName)
215 {
216 std::unique_lock<std::mutex> lock(mutex_);
217 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
218 if (currTwoPhaseTask_ == nullptr) {
219 return EnqueueTask(task, PlayerServerTaskType::SEEKING, taskName);
220 }
221 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
222 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
223 pendingTwoPhaseTasks_.push_back({ PlayerServerTaskType::SEEKING, task, nullptr, taskName });
224 return MSERR_OK;
225 }
226
SetVideoSurfaeTask(const std::shared_ptr<ITaskHandler> & task,const std::string & taskName)227 int32_t PlayerServerTaskMgr::SetVideoSurfaeTask(const std::shared_ptr<ITaskHandler> &task, const std::string &taskName)
228 {
229 std::unique_lock<std::mutex> lock(mutex_);
230 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
231 if (currTwoPhaseTask_ == nullptr) {
232 return EnqueueTask(task, PlayerServerTaskType::SET_VIDEO_SURFACE, taskName);
233 }
234 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
235 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
236 pendingTwoPhaseTasks_.push_back({ PlayerServerTaskType::SET_VIDEO_SURFACE, task, nullptr, taskName });
237 return MSERR_OK;
238 }
239
MarkTaskDone(const std::string & taskName)240 int32_t PlayerServerTaskMgr::MarkTaskDone(const std::string &taskName)
241 {
242 std::unique_lock<std::mutex> lock(mutex_);
243 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
244
245 if (taskName.compare("volume done") == 0) {
246 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] end", FAKE_POINTER(this), taskName.c_str());
247 } else {
248 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] end", FAKE_POINTER(this), taskName.c_str());
249 }
250 currTwoPhaseTask_ = nullptr;
251 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
252 currTwoPhaseTaskName_ = "None";
253 currentSeekMode_ = -1;
254 currentSeekTime_ = -1;
255
256 if (!pendingTwoPhaseTasks_.empty()) {
257 auto item = pendingTwoPhaseTasks_.front();
258 pendingTwoPhaseTasks_.pop_front();
259 currTwoPhaseType_ = item.type;
260 if (item.type == PlayerServerTaskType::CANCEL_TASK) {
261 currTwoPhaseTask_ = item.cancelTask;
262 } else {
263 currTwoPhaseTask_ = item.task;
264 }
265 currTwoPhaseTaskName_ = item.taskName;
266 if (item.type == PlayerServerTaskType::SEEKING) {
267 currentSeekMode_ = item.seekMode_;
268 currentSeekTime_ = item.seekTime_;
269 }
270
271 CHECK_AND_RETURN_RET_LOG(currTwoPhaseTask_ != nullptr, MSERR_OK, "task is nullptr");
272 int32_t ret = taskThread_->EnqueueTask(currTwoPhaseTask_);
273 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret,
274 "execute the stack top task failed, type: %{public}hhu", item.type);
275
276 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] start",
277 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str());
278 }
279 return MSERR_OK;
280 }
281
ClearAllTask()282 void PlayerServerTaskMgr::ClearAllTask()
283 {
284 MEDIA_LOGD("enter");
285 std::unique_lock<std::mutex> lock(mutex_);
286 CHECK_AND_RETURN_LOG(isInited_, "not init");
287
288 currTwoPhaseTask_ = nullptr;
289 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
290 pendingTwoPhaseTasks_.clear();
291
292 auto dummyTask = std::make_shared<TaskHandler<void>>([this]() {
293 MEDIA_LOGD("0x%{public}06" PRIXPTR " execute dummy task...", FAKE_POINTER(this));
294 });
295 (void)taskThread_->EnqueueTask(dummyTask, true, 0);
296 MEDIA_LOGD("exit");
297 }
298
Reset()299 int32_t PlayerServerTaskMgr::Reset()
300 {
301 MEDIA_LOGD("enter");
302 std::unique_lock<std::mutex> lock(mutex_);
303
304 currTwoPhaseTask_ = nullptr;
305 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
306 pendingTwoPhaseTasks_.clear();
307 isInited_ = false;
308
309 if (taskThread_ != nullptr) {
310 std::unique_ptr<TaskQueue> tmp;
311 std::swap(tmp, taskThread_);
312
313 lock.unlock();
314 int32_t ret = tmp->Stop();
315 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "stop task thread failed");
316 lock.lock();
317 }
318
319 MEDIA_LOGD("exit");
320 return MSERR_OK;
321 }
322 }
323 }