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
SeekContinousTask(const std::shared_ptr<ITaskHandler> & task,const std::string & taskName)178 int32_t PlayerServerTaskMgr::SeekContinousTask(const std::shared_ptr<ITaskHandler> &task, const std::string &taskName)
179 {
180 std::unique_lock<std::mutex> lock(mutex_);
181 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
182 if (currTwoPhaseTask_ == nullptr) {
183 return EnqueueTask(task, PlayerServerTaskType::SEEKING, taskName);
184 }
185 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
186 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
187 pendingTwoPhaseTasks_.push_back({ PlayerServerTaskType::SEEKING, task, nullptr, taskName });
188 return MSERR_OK;
189 }
190
SetVideoSurfaeTask(const std::shared_ptr<ITaskHandler> & task,const std::string & taskName)191 int32_t PlayerServerTaskMgr::SetVideoSurfaeTask(const std::shared_ptr<ITaskHandler> &task, const std::string &taskName)
192 {
193 std::unique_lock<std::mutex> lock(mutex_);
194 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
195 if (currTwoPhaseTask_ == nullptr) {
196 return EnqueueTask(task, PlayerServerTaskType::SET_VIDEO_SURFACE, taskName);
197 }
198 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] is in processing, the new task[%{public}s]",
199 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str(), taskName.c_str());
200 pendingTwoPhaseTasks_.push_back({ PlayerServerTaskType::SET_VIDEO_SURFACE, task, nullptr, taskName });
201 return MSERR_OK;
202 }
203
MarkTaskDone(const std::string & taskName)204 int32_t PlayerServerTaskMgr::MarkTaskDone(const std::string &taskName)
205 {
206 std::unique_lock<std::mutex> lock(mutex_);
207 CHECK_AND_RETURN_RET_LOG(isInited_, MSERR_INVALID_OPERATION, "not init");
208
209 if (taskName.compare("volume done") == 0) {
210 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] end", FAKE_POINTER(this), taskName.c_str());
211 } else {
212 MEDIA_LOGI("0x%{public}06" PRIXPTR " task[%{public}s] end", FAKE_POINTER(this), taskName.c_str());
213 }
214 currTwoPhaseTask_ = nullptr;
215 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
216 currTwoPhaseTaskName_ = "None";
217 currentSeekMode_ = -1;
218 currentSeekTime_ = -1;
219
220 if (!pendingTwoPhaseTasks_.empty()) {
221 auto item = pendingTwoPhaseTasks_.front();
222 pendingTwoPhaseTasks_.pop_front();
223 currTwoPhaseType_ = item.type;
224 if (item.type == PlayerServerTaskType::CANCEL_TASK) {
225 currTwoPhaseTask_ = item.cancelTask;
226 } else {
227 currTwoPhaseTask_ = item.task;
228 }
229 currTwoPhaseTaskName_ = item.taskName;
230 if (item.type == PlayerServerTaskType::SEEKING) {
231 currentSeekMode_ = item.seekMode_;
232 currentSeekTime_ = item.seekTime_;
233 }
234
235 CHECK_AND_RETURN_RET_LOG(currTwoPhaseTask_ != nullptr, MSERR_OK, "task is nullptr");
236 int32_t ret = taskThread_->EnqueueTask(currTwoPhaseTask_);
237 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret,
238 "execute the stack top task failed, type: %{public}hhu", item.type);
239
240 MEDIA_LOGD("0x%{public}06" PRIXPTR " task[%{public}s] start",
241 FAKE_POINTER(this), currTwoPhaseTaskName_.c_str());
242 }
243 return MSERR_OK;
244 }
245
ClearAllTask()246 void PlayerServerTaskMgr::ClearAllTask()
247 {
248 MEDIA_LOGD("enter");
249 std::unique_lock<std::mutex> lock(mutex_);
250 CHECK_AND_RETURN_LOG(isInited_, "not init");
251
252 currTwoPhaseTask_ = nullptr;
253 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
254 pendingTwoPhaseTasks_.clear();
255
256 auto dummyTask = std::make_shared<TaskHandler<void>>([this]() {
257 MEDIA_LOGD("0x%{public}06" PRIXPTR " execute dummy task...", FAKE_POINTER(this));
258 });
259 (void)taskThread_->EnqueueTask(dummyTask, true, 0);
260 MEDIA_LOGD("exit");
261 }
262
Reset()263 int32_t PlayerServerTaskMgr::Reset()
264 {
265 MEDIA_LOGD("enter");
266 std::unique_lock<std::mutex> lock(mutex_);
267
268 currTwoPhaseTask_ = nullptr;
269 currTwoPhaseType_ = PlayerServerTaskType::BUTT;
270 pendingTwoPhaseTasks_.clear();
271 isInited_ = false;
272
273 if (taskThread_ != nullptr) {
274 std::unique_ptr<TaskQueue> tmp;
275 std::swap(tmp, taskThread_);
276
277 lock.unlock();
278 int32_t ret = tmp->Stop();
279 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "stop task thread failed");
280 lock.lock();
281 }
282
283 MEDIA_LOGD("exit");
284 return MSERR_OK;
285 }
286 }
287 }
288