1 /*
2 * Copyright (c) 2022-2022 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 HST_LOG_TAG "CallbackLooper"
17
18 #include "hiplayer_callback_looper.h"
19 #include <utility>
20 #include "common/log.h"
21 #include "osal/task/autolock.h"
22 #include "osal/utils/steady_clock.h"
23
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "HiPlayerCallbackLooper" };
26 }
27
28 namespace OHOS {
29 namespace Media {
30 namespace {
31 constexpr int32_t WHAT_NONE = 0;
32 constexpr int32_t WHAT_MEDIA_PROGRESS = 1;
33 constexpr int32_t WHAT_INFO = 2;
34 constexpr int32_t WHAT_ERROR = 3;
35 constexpr int32_t WHAT_COLLECT_AMPLITUDE = 4;
36 constexpr int32_t WHAT_SYSTEM_OPERATION = 5;
37 constexpr int32_t WHAT_DFX_INFO = 6;
38
39 constexpr int32_t TUPLE_POS_0 = 0;
40 constexpr int32_t TUPLE_POS_1 = 1;
41 constexpr int32_t TUPLE_POS_2 = 2;
42 constexpr int32_t MAX_AMPLITUDE_SIZE = 5;
43 }
HiPlayerCallbackLooper()44 HiPlayerCallbackLooper::HiPlayerCallbackLooper()
45 {
46 }
47
~HiPlayerCallbackLooper()48 HiPlayerCallbackLooper::~HiPlayerCallbackLooper()
49 {
50 Stop();
51 }
52
IsStarted()53 bool HiPlayerCallbackLooper::IsStarted()
54 {
55 return taskStarted_;
56 }
57
Stop()58 void HiPlayerCallbackLooper::Stop()
59 {
60 if (taskStarted_) {
61 task_->Stop();
62 taskStarted_ = false;
63 }
64 }
65
SetMaxAmplitudeCbStatus(bool status)66 void HiPlayerCallbackLooper::SetMaxAmplitudeCbStatus(bool status)
67 {
68 MEDIA_LOG_I("HiPlayerCallbackLooper SetMaxAmplitudeCbStatus");
69 OHOS::Media::AutoLock lock(loopMutex_);
70 FALSE_RETURN(reportUV_ != status);
71
72 reportUV_ = status;
73 FALSE_RETURN(reportUV_ && collectMaxAmplitude_ && !reportUVProgressLoopRunning_);
74 reportUVProgressLoopRunning_ = true;
75 Enqueue(std::make_shared<Event>(WHAT_COLLECT_AMPLITUDE,
76 SteadyClock::GetCurrentTimeMs() + collectMaxAmplitudeIntervalMs_, Any()));
77 }
78
StartWithPlayerEngineObs(const std::weak_ptr<IPlayerEngineObs> & obs)79 void HiPlayerCallbackLooper::StartWithPlayerEngineObs(const std::weak_ptr<IPlayerEngineObs>& obs)
80 {
81 OHOS::Media::AutoLock lock(loopMutex_);
82 obs_ = obs;
83 if (!taskStarted_) {
84 task_->Start();
85 taskStarted_ = true;
86 MEDIA_LOG_I("start callback looper");
87 }
88 }
SetPlayEngine(IPlayerEngine * engine,std::string playerId)89 void HiPlayerCallbackLooper::SetPlayEngine(IPlayerEngine* engine, std::string playerId)
90 {
91 OHOS::Media::AutoLock lock(loopMutex_);
92 playerEngine_ = engine;
93 task_ = std::make_unique<Task>("callbackThread", playerId, TaskType::GLOBAL, TaskPriority::NORMAL, false);
94 }
95
EnableReportMediaProgress(bool enable)96 void HiPlayerCallbackLooper::EnableReportMediaProgress(bool enable)
97 {
98 MEDIA_LOG_D("EnableReportMediaProgress, enable: " PUBLIC_LOG_D32, static_cast<int32_t>(enable));
99 OHOS::Media::AutoLock lock(loopMutex_);
100 FALSE_RETURN(enableReportMediaProgress_ != enable);
101 enableReportMediaProgress_ = enable;
102 FALSE_RETURN(reportMediaProgress_ && enableReportMediaProgress_ && !isReportMediaProgressLoopRunning_);
103 isReportMediaProgressLoopRunning_ = true;
104 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS,
105 SteadyClock::GetCurrentTimeMs() + reportProgressIntervalMs_, Any()));
106 }
107
StartReportMediaProgress(int64_t updateIntervalMs)108 void HiPlayerCallbackLooper::StartReportMediaProgress(int64_t updateIntervalMs)
109 {
110 MEDIA_LOG_I("HiPlayerCallbackLooper StartReportMediaProgress");
111 OHOS::Media::AutoLock lock(loopMutex_);
112 reportProgressIntervalMs_ = updateIntervalMs;
113 if (reportMediaProgress_) { // already set
114 return;
115 }
116 reportMediaProgress_ = true;
117 FALSE_RETURN(enableReportMediaProgress_);
118 isReportMediaProgressLoopRunning_ = true;
119 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS,
120 SteadyClock::GetCurrentTimeMs() + reportProgressIntervalMs_, Any()));
121 }
122
StartCollectMaxAmplitude(int64_t updateIntervalMs)123 void HiPlayerCallbackLooper::StartCollectMaxAmplitude(int64_t updateIntervalMs)
124 {
125 MEDIA_LOG_I("HiPlayerCallbackLooper StartCollectMaxAmplitude");
126 OHOS::Media::AutoLock lock(loopMutex_);
127 collectMaxAmplitudeIntervalMs_ = updateIntervalMs;
128 if (collectMaxAmplitude_) { // already set
129 return;
130 }
131 collectMaxAmplitude_ = true;
132 FALSE_RETURN(reportUV_);
133 reportUVProgressLoopRunning_ = true;
134 Enqueue(std::make_shared<Event>(WHAT_COLLECT_AMPLITUDE,
135 SteadyClock::GetCurrentTimeMs() + collectMaxAmplitudeIntervalMs_, Any()));
136 }
137
ManualReportMediaProgressOnce()138 void HiPlayerCallbackLooper::ManualReportMediaProgressOnce()
139 {
140 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS, SteadyClock::GetCurrentTimeMs(), Any()));
141 }
142
StopReportMediaProgress()143 void HiPlayerCallbackLooper::StopReportMediaProgress()
144 {
145 MEDIA_LOG_D("HiPlayerCallbackLooper StopReportMediaProgress");
146 OHOS::Media::AutoLock lock(loopMutex_);
147 reportMediaProgress_ = false;
148 }
149
StopCollectMaxAmplitude()150 void HiPlayerCallbackLooper::StopCollectMaxAmplitude()
151 {
152 MEDIA_LOG_D("HiPlayerCallbackLooper StopCollectMaxAmplitude");
153 OHOS::Media::AutoLock lock(loopMutex_);
154 collectMaxAmplitude_ = false;
155 }
156
DoReportCompletedTime()157 void HiPlayerCallbackLooper::DoReportCompletedTime()
158 {
159 OHOS::Media::AutoLock lock(loopMutex_);
160 auto obs = obs_.lock();
161 if (obs) {
162 Format format;
163 int32_t playRangeEndTime = static_cast<int32_t>(playerEngine_->GetPlayRangeEndTime());
164 if (playRangeEndTime != -1) {
165 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS endTime position updated: " PUBLIC_LOG_D32, playRangeEndTime);
166 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, playRangeEndTime, format);
167 } else {
168 int32_t currentPositionMs;
169 if (playerEngine_->GetDuration(currentPositionMs) == 0) {
170 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS completed position updated: " PUBLIC_LOG_D32, currentPositionMs);
171 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, currentPositionMs, format);
172 } else {
173 MEDIA_LOG_W("get player engine current time error");
174 }
175 }
176 }
177 }
178
DoReportMediaProgress()179 void HiPlayerCallbackLooper::DoReportMediaProgress()
180 {
181 OHOS::Media::AutoLock lock(loopMutex_);
182 if (!reportMediaProgress_ || !enableReportMediaProgress_) {
183 isReportMediaProgressLoopRunning_ = false;
184 return;
185 }
186 auto obs = obs_.lock();
187 if (obs && !isDropMediaProgress_) {
188 Format format;
189 int32_t currentPositionMs;
190 if (playerEngine_->GetCurrentTime(currentPositionMs) == 0) {
191 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS position updated: " PUBLIC_LOG_D32, currentPositionMs);
192 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, currentPositionMs, format);
193 } else {
194 MEDIA_LOG_D("get player engine current time error");
195 }
196 }
197 isDropMediaProgress_ = false;
198 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS,
199 SteadyClock::GetCurrentTimeMs() + reportProgressIntervalMs_, Any()));
200 }
201
DoCollectAmplitude()202 void HiPlayerCallbackLooper::DoCollectAmplitude()
203 {
204 OHOS::Media::AutoLock lock(loopMutex_);
205 if (!collectMaxAmplitude_ || !reportUV_) {
206 reportUVProgressLoopRunning_ = false;
207 return;
208 }
209 auto obs = obs_.lock();
210 if (obs) {
211 float maxAmplitude = 0.0f;
212 maxAmplitude = playerEngine_->GetMaxAmplitude();
213 vMaxAmplitudeArray_.push_back(maxAmplitude);
214 if (vMaxAmplitudeArray_.size() == MAX_AMPLITUDE_SIZE) {
215 int mSize = static_cast<int>(vMaxAmplitudeArray_.size());
216 const int size = mSize;
217 float* maxAmplitudeArray = vMaxAmplitudeArray_.data();
218 Format amplitudeFormat;
219 (void)amplitudeFormat.PutBuffer(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE),
220 static_cast<uint8_t *>(static_cast<void *>(maxAmplitudeArray)), size * sizeof(float));
221 obs->OnInfo(INFO_TYPE_MAX_AMPLITUDE_COLLECT, 0, amplitudeFormat);
222 vMaxAmplitudeArray_.clear();
223 }
224 }
225
226 Enqueue(std::make_shared<Event>(WHAT_COLLECT_AMPLITUDE,
227 SteadyClock::GetCurrentTimeMs() + collectMaxAmplitudeIntervalMs_, Any()));
228 }
229
ReportRemainedMaxAmplitude()230 void HiPlayerCallbackLooper::ReportRemainedMaxAmplitude()
231 {
232 OHOS::Media::AutoLock lock(loopMutex_);
233 auto obs = obs_.lock();
234 if (obs != nullptr) {
235 if (vMaxAmplitudeArray_.size() != 0) {
236 const int size = static_cast<int>(vMaxAmplitudeArray_.size());
237 float* maxAmplitudeArray = vMaxAmplitudeArray_.data();
238 Format amplitudeFormat;
239 (void)amplitudeFormat.PutBuffer(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE),
240 static_cast<uint8_t *>(static_cast<void *>(maxAmplitudeArray)), size * sizeof(float));
241 obs->OnInfo(INFO_TYPE_MAX_AMPLITUDE_COLLECT, 0, amplitudeFormat);
242 vMaxAmplitudeArray_.clear();
243 }
244 }
245 }
246
DoReportSystemOperation(const Any & info)247 void HiPlayerCallbackLooper::DoReportSystemOperation(const Any& info)
248 {
249 std::shared_ptr<IPlayerEngineObs> obs;
250 {
251 OHOS::Media::AutoLock lock(loopMutex_);
252 obs = obs_.lock();
253 }
254 if (obs) {
255 auto ptr = AnyCast<std::pair<PlayerOnSystemOperationType, PlayerOperationReason>>(&info);
256 if (ptr == nullptr) {
257 MEDIA_LOG_E_SHORT("DoReportSystemOperation, ptr is nullptr");
258 return;
259 }
260 MEDIA_LOG_I("Do Report SystemOperation, type: " PUBLIC_LOG_D32 " resaon: " PUBLIC_LOG_D32,
261 static_cast<int32_t>(ptr->first), static_cast<int32_t>(ptr->second));
262 obs->OnSystemOperation(ptr->first, ptr->second);
263 }
264 }
265
OnError(PlayerErrorType errorType,int32_t errorCode)266 void HiPlayerCallbackLooper::OnError(PlayerErrorType errorType, int32_t errorCode)
267 {
268 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_ERROR, SteadyClock::GetCurrentTimeMs(),
269 std::make_pair(errorType, errorCode)));
270 }
271
DoReportError(const Any & error)272 void HiPlayerCallbackLooper::DoReportError(const Any &error)
273 {
274 OHOS::Media::AutoLock lock(loopMutex_);
275 auto obs = obs_.lock();
276 if (obs != nullptr) {
277 auto ptr = AnyCast<std::pair<PlayerErrorType, int32_t>>(&error);
278 if (ptr == nullptr) {
279 MEDIA_LOG_E_SHORT("DoReportError error, ptr is nullptr");
280 return;
281 }
282 MEDIA_LOG_E("Report error, error type: " PUBLIC_LOG_D32 " error value: " PUBLIC_LOG_D32,
283 static_cast<int32_t>(ptr->first), static_cast<int32_t>(ptr->second));
284 obs->OnError(ptr->first, ptr->second);
285 }
286 }
287
OnSystemOperation(PlayerOnSystemOperationType type,PlayerOperationReason reason)288 void HiPlayerCallbackLooper::OnSystemOperation(PlayerOnSystemOperationType type, PlayerOperationReason reason)
289 {
290 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_SYSTEM_OPERATION, SteadyClock::GetCurrentTimeMs(),
291 std::make_pair(type, reason)));
292 }
293
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)294 void HiPlayerCallbackLooper::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
295 {
296 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_INFO, SteadyClock::GetCurrentTimeMs(),
297 std::make_tuple(type, extra, infoBody)));
298 }
299
OnDfxInfo(const DfxEvent & event)300 void HiPlayerCallbackLooper::OnDfxInfo(const DfxEvent &event)
301 {
302 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_DFX_INFO, SteadyClock::GetCurrentTimeMs(), event));
303 }
304
DoReportDfxInfo(const Any & info)305 void HiPlayerCallbackLooper::DoReportDfxInfo(const Any& info)
306 {
307 auto obs = obs_.lock();
308 if (obs != nullptr) {
309 auto ptr = AnyCast<DfxEvent>(&info);
310 if (ptr == nullptr) {
311 MEDIA_LOG_E_SHORT("DoReportDfxInfo error, ptr is nullptr");
312 return;
313 }
314 MEDIA_LOG_DD("Report Dfx, callerName: " PUBLIC_LOG_S " type: " PUBLIC_LOG_D32,
315 ptr->callerName.c_str(), static_cast<int32_t>(ptr->type));
316 obs->OnDfxInfo(*ptr);
317 }
318 }
319
DoReportInfo(const Any & info)320 void HiPlayerCallbackLooper::DoReportInfo(const Any& info)
321 {
322 auto obs = obs_.lock();
323 if (obs != nullptr) {
324 auto ptr = AnyCast<std::tuple<PlayerOnInfoType, int32_t, Format>>(&info);
325 if (ptr == nullptr) {
326 MEDIA_LOG_E_SHORT("DoReportInfo error, ptr is nullptr");
327 return;
328 }
329 MEDIA_LOG_D("Report info, info type: " PUBLIC_LOG_D32 " info value: " PUBLIC_LOG_D32,
330 static_cast<int32_t>(std::get<TUPLE_POS_0>(*ptr)), static_cast<int32_t>(std::get<TUPLE_POS_1>(*ptr)));
331 obs->OnInfo(std::get<TUPLE_POS_0>(*ptr), std::get<TUPLE_POS_1>(*ptr), std::get<TUPLE_POS_2>(*ptr));
332 }
333 }
334
LoopOnce(const std::shared_ptr<HiPlayerCallbackLooper::Event> & item)335 void HiPlayerCallbackLooper::LoopOnce(const std::shared_ptr<HiPlayerCallbackLooper::Event>& item)
336 {
337 switch (item->what) {
338 case WHAT_MEDIA_PROGRESS:
339 DoReportMediaProgress();
340 break;
341 case WHAT_INFO:
342 DoReportInfo(item->detail);
343 break;
344 case WHAT_ERROR:
345 DoReportError(item->detail);
346 break;
347 case WHAT_COLLECT_AMPLITUDE:
348 DoCollectAmplitude();
349 break;
350 case WHAT_SYSTEM_OPERATION:
351 DoReportSystemOperation(item->detail);
352 break;
353 case WHAT_DFX_INFO:
354 DoReportDfxInfo(item->detail);
355 break;
356 default:
357 break;
358 }
359 }
360
Enqueue(const std::shared_ptr<HiPlayerCallbackLooper::Event> & event)361 void HiPlayerCallbackLooper::Enqueue(const std::shared_ptr<HiPlayerCallbackLooper::Event>& event)
362 {
363 if (!event) {
364 return;
365 }
366 if (event->what == WHAT_NONE) {
367 MEDIA_LOG_I("invalid event");
368 }
369 int64_t delayUs = (event->whenMs - SteadyClock::GetCurrentTimeMs()) * 1000;
370 task_->SubmitJob([this, event]() {
371 LoopOnce(event);
372 }, delayUs);
373 }
374
OnInfoDelay(PlayerOnInfoType type,int32_t extra,const Format & infoBody,int64_t delayMs)375 void HiPlayerCallbackLooper::OnInfoDelay(PlayerOnInfoType type, int32_t extra, const Format &infoBody, int64_t delayMs)
376 {
377 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_INFO, SteadyClock::GetCurrentTimeMs() + delayMs,
378 std::make_tuple(type, extra, infoBody)));
379 }
380 } // namespace Media
381 } // namespace OHOS