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
38 constexpr int32_t TUPLE_POS_0 = 0;
39 constexpr int32_t TUPLE_POS_1 = 1;
40 constexpr int32_t TUPLE_POS_2 = 2;
41 constexpr int32_t MAX_AMPLITUDE_SIZE = 5;
42 }
HiPlayerCallbackLooper()43 HiPlayerCallbackLooper::HiPlayerCallbackLooper()
44 {
45 }
46
~HiPlayerCallbackLooper()47 HiPlayerCallbackLooper::~HiPlayerCallbackLooper()
48 {
49 Stop();
50 }
51
IsStarted()52 bool HiPlayerCallbackLooper::IsStarted()
53 {
54 return taskStarted_;
55 }
56
Stop()57 void HiPlayerCallbackLooper::Stop()
58 {
59 if (taskStarted_) {
60 task_->Stop();
61 taskStarted_ = false;
62 }
63 }
64
StartWithPlayerEngineObs(const std::weak_ptr<IPlayerEngineObs> & obs)65 void HiPlayerCallbackLooper::StartWithPlayerEngineObs(const std::weak_ptr<IPlayerEngineObs>& obs)
66 {
67 OHOS::Media::AutoLock lock(loopMutex_);
68 obs_ = obs;
69 if (!taskStarted_) {
70 task_->Start();
71 taskStarted_ = true;
72 MEDIA_LOG_I("start callback looper");
73 }
74 }
SetPlayEngine(IPlayerEngine * engine,std::string playerId)75 void HiPlayerCallbackLooper::SetPlayEngine(IPlayerEngine* engine, std::string playerId)
76 {
77 OHOS::Media::AutoLock lock(loopMutex_);
78 playerEngine_ = engine;
79 task_ = std::make_unique<Task>("callbackThread", playerId, TaskType::GLOBAL, TaskPriority::NORMAL, false);
80 }
81
StartReportMediaProgress(int64_t updateIntervalMs)82 void HiPlayerCallbackLooper::StartReportMediaProgress(int64_t updateIntervalMs)
83 {
84 MEDIA_LOG_I("HiPlayerCallbackLooper StartReportMediaProgress");
85 reportProgressIntervalMs_ = updateIntervalMs;
86 if (reportMediaProgress_) { // already set
87 return;
88 }
89 reportMediaProgress_ = true;
90 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS,
91 SteadyClock::GetCurrentTimeMs() + reportProgressIntervalMs_, Any()));
92 }
93
startCollectMaxAmplitude(int64_t updateIntervalMs)94 void HiPlayerCallbackLooper::startCollectMaxAmplitude(int64_t updateIntervalMs)
95 {
96 MEDIA_LOG_I("HiPlayerCallbackLooper startCollectMaxAmplitude");
97 collectMaxAmplitudeIntervalMs_ = updateIntervalMs;
98 if (collectMaxAmplitude_) { // already set
99 return;
100 }
101 collectMaxAmplitude_ = true;
102 Enqueue(std::make_shared<Event>(WHAT_COLLECT_AMPLITUDE,
103 SteadyClock::GetCurrentTimeMs() + collectMaxAmplitudeIntervalMs_, Any()));
104 }
105
ManualReportMediaProgressOnce()106 void HiPlayerCallbackLooper::ManualReportMediaProgressOnce()
107 {
108 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS, SteadyClock::GetCurrentTimeMs(), Any()));
109 }
110
StopReportMediaProgress()111 void HiPlayerCallbackLooper::StopReportMediaProgress()
112 {
113 MEDIA_LOG_I("HiPlayerCallbackLooper StopReportMediaProgress");
114 OHOS::Media::AutoLock lock(loopMutex_);
115 reportMediaProgress_ = false;
116 }
117
StopCollectMaxAmplitude()118 void HiPlayerCallbackLooper::StopCollectMaxAmplitude()
119 {
120 MEDIA_LOG_I("HiPlayerCallbackLooper StopCollectMaxAmplitude");
121 OHOS::Media::AutoLock lock(loopMutex_);
122 collectMaxAmplitude_ = false;
123 }
124
DoReportCompletedTime()125 void HiPlayerCallbackLooper::DoReportCompletedTime()
126 {
127 OHOS::Media::AutoLock lock(loopMutex_);
128 auto obs = obs_.lock();
129 if (obs) {
130 Format format;
131 int32_t playRangeEndTime = static_cast<int32_t>(playerEngine_->GetPlayRangeEndTime());
132 if (playRangeEndTime != -1) {
133 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS endTime position updated: " PUBLIC_LOG_D32, playRangeEndTime);
134 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, playRangeEndTime, format);
135 } else {
136 int32_t currentPositionMs;
137 if (playerEngine_->GetDuration(currentPositionMs) == 0) {
138 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS completed position updated: " PUBLIC_LOG_D32, currentPositionMs);
139 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, currentPositionMs, format);
140 } else {
141 MEDIA_LOG_W("get player engine current time error");
142 }
143 }
144 }
145 }
146
DoReportMediaProgress()147 void HiPlayerCallbackLooper::DoReportMediaProgress()
148 {
149 OHOS::Media::AutoLock lock(loopMutex_);
150 if (!reportMediaProgress_) {
151 return;
152 }
153 auto obs = obs_.lock();
154 if (obs && !isDropMediaProgress_) {
155 Format format;
156 int32_t currentPositionMs;
157 if (playerEngine_->GetCurrentTime(currentPositionMs) == 0) {
158 MEDIA_LOG_D("EVENT_AUDIO_PROGRESS position updated: " PUBLIC_LOG_D32, currentPositionMs);
159 obs->OnInfo(INFO_TYPE_POSITION_UPDATE, currentPositionMs, format);
160 } else {
161 MEDIA_LOG_W("get player engine current time error");
162 }
163 }
164 isDropMediaProgress_ = false;
165 if (reportMediaProgress_) {
166 Enqueue(std::make_shared<Event>(WHAT_MEDIA_PROGRESS,
167 SteadyClock::GetCurrentTimeMs() + reportProgressIntervalMs_, Any()));
168 }
169 }
170
DoCollectAmplitude()171 void HiPlayerCallbackLooper::DoCollectAmplitude()
172 {
173 OHOS::Media::AutoLock lock(loopMutex_);
174 if (!collectMaxAmplitude_) {
175 return;
176 }
177 auto obs = obs_.lock();
178 if (obs) {
179 float maxAmplitude = 0.0f;
180 maxAmplitude = playerEngine_->GetMaxAmplitude();
181 vMaxAmplitudeArray_.push_back(maxAmplitude);
182 if (vMaxAmplitudeArray_.size() == MAX_AMPLITUDE_SIZE) {
183 int mSize = static_cast<int>(vMaxAmplitudeArray_.size());
184 const int size = mSize;
185 float* maxAmplitudeArray = vMaxAmplitudeArray_.data();
186 Format amplitudeFormat;
187 (void)amplitudeFormat.PutBuffer(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE),
188 static_cast<uint8_t *>(static_cast<void *>(maxAmplitudeArray)), size * sizeof(float));
189 obs->OnInfo(INFO_TYPE_MAX_AMPLITUDE_COLLECT, 0, amplitudeFormat);
190 vMaxAmplitudeArray_.clear();
191 }
192 }
193 if (collectMaxAmplitude_) {
194 Enqueue(std::make_shared<Event>(WHAT_COLLECT_AMPLITUDE,
195 SteadyClock::GetCurrentTimeMs() + collectMaxAmplitudeIntervalMs_, Any()));
196 }
197 }
198
ReportRemainedMaxAmplitude()199 void HiPlayerCallbackLooper::ReportRemainedMaxAmplitude()
200 {
201 OHOS::Media::AutoLock lock(loopMutex_);
202 auto obs = obs_.lock();
203 if (obs != nullptr) {
204 if (vMaxAmplitudeArray_.size() != 0) {
205 const int size = static_cast<int>(vMaxAmplitudeArray_.size());
206 float* maxAmplitudeArray = vMaxAmplitudeArray_.data();
207 Format amplitudeFormat;
208 (void)amplitudeFormat.PutBuffer(std::string(PlayerKeys::AUDIO_MAX_AMPLITUDE),
209 static_cast<uint8_t *>(static_cast<void *>(maxAmplitudeArray)), size * sizeof(float));
210 obs->OnInfo(INFO_TYPE_MAX_AMPLITUDE_COLLECT, 0, amplitudeFormat);
211 vMaxAmplitudeArray_.clear();
212 }
213 }
214 }
215
DoReportSystemOperation(const Any & info)216 void HiPlayerCallbackLooper::DoReportSystemOperation(const Any& info)
217 {
218 OHOS::Media::AutoLock lock(loopMutex_);
219 auto obs = obs_.lock();
220 if (obs) {
221 auto ptr = AnyCast<std::pair<PlayerOnSystemOperationType, PlayerOperationReason>>(&info);
222 if (ptr == nullptr) {
223 MEDIA_LOG_E_SHORT("DoReportSystemOperation, ptr is nullptr");
224 return;
225 }
226 MEDIA_LOG_I("Do Report SystemOperation, type: " PUBLIC_LOG_D32 " resaon: " PUBLIC_LOG_D32,
227 static_cast<int32_t>(ptr->first), static_cast<int32_t>(ptr->second));
228 obs->OnSystemOperation(ptr->first, ptr->second);
229 }
230 }
231
OnError(PlayerErrorType errorType,int32_t errorCode)232 void HiPlayerCallbackLooper::OnError(PlayerErrorType errorType, int32_t errorCode)
233 {
234 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_ERROR, SteadyClock::GetCurrentTimeMs(),
235 std::make_pair(errorType, errorCode)));
236 }
237
DoReportError(const Any & error)238 void HiPlayerCallbackLooper::DoReportError(const Any &error)
239 {
240 OHOS::Media::AutoLock lock(loopMutex_);
241 auto obs = obs_.lock();
242 if (obs != nullptr) {
243 auto ptr = AnyCast<std::pair<PlayerErrorType, int32_t>>(&error);
244 if (ptr == nullptr) {
245 MEDIA_LOG_E_SHORT("DoReportError error, ptr is nullptr");
246 return;
247 }
248 MEDIA_LOG_E("Report error, error type: " PUBLIC_LOG_D32 " error value: " PUBLIC_LOG_D32,
249 static_cast<int32_t>(ptr->first), static_cast<int32_t>(ptr->second));
250 obs->OnError(ptr->first, ptr->second);
251 }
252 }
253
OnSystemOperation(PlayerOnSystemOperationType type,PlayerOperationReason reason)254 void HiPlayerCallbackLooper::OnSystemOperation(PlayerOnSystemOperationType type, PlayerOperationReason reason)
255 {
256 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_SYSTEM_OPERATION, SteadyClock::GetCurrentTimeMs(),
257 std::make_pair(type, reason)));
258 }
259
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)260 void HiPlayerCallbackLooper::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
261 {
262 Enqueue(std::make_shared<HiPlayerCallbackLooper::Event>(WHAT_INFO, SteadyClock::GetCurrentTimeMs(),
263 std::make_tuple(type, extra, infoBody)));
264 }
265
DoReportInfo(const Any & info)266 void HiPlayerCallbackLooper::DoReportInfo(const Any& info)
267 {
268 auto obs = obs_.lock();
269 if (obs != nullptr) {
270 auto ptr = AnyCast<std::tuple<PlayerOnInfoType, int32_t, Format>>(&info);
271 if (ptr == nullptr) {
272 MEDIA_LOG_E_SHORT("DoReportInfo error, ptr is nullptr");
273 return;
274 }
275 MEDIA_LOG_I("Report info, info type: " PUBLIC_LOG_D32 " info value: " PUBLIC_LOG_D32,
276 static_cast<int32_t>(std::get<TUPLE_POS_0>(*ptr)), static_cast<int32_t>(std::get<TUPLE_POS_1>(*ptr)));
277 obs->OnInfo(std::get<TUPLE_POS_0>(*ptr), std::get<TUPLE_POS_1>(*ptr), std::get<TUPLE_POS_2>(*ptr));
278 }
279 }
280
LoopOnce(const std::shared_ptr<HiPlayerCallbackLooper::Event> & item)281 void HiPlayerCallbackLooper::LoopOnce(const std::shared_ptr<HiPlayerCallbackLooper::Event>& item)
282 {
283 switch (item->what) {
284 case WHAT_MEDIA_PROGRESS:
285 DoReportMediaProgress();
286 break;
287 case WHAT_INFO:
288 DoReportInfo(item->detail);
289 break;
290 case WHAT_ERROR:
291 DoReportError(item->detail);
292 break;
293 case WHAT_COLLECT_AMPLITUDE:
294 DoCollectAmplitude();
295 break;
296 case WHAT_SYSTEM_OPERATION:
297 DoReportSystemOperation(item->detail);
298 break;
299 default:
300 break;
301 }
302 }
303
Enqueue(const std::shared_ptr<HiPlayerCallbackLooper::Event> & event)304 void HiPlayerCallbackLooper::Enqueue(const std::shared_ptr<HiPlayerCallbackLooper::Event>& event)
305 {
306 if (event->what == WHAT_NONE) {
307 MEDIA_LOG_I("invalid event");
308 }
309 int64_t delayUs = (event->whenMs - SteadyClock::GetCurrentTimeMs()) * 1000;
310 task_->SubmitJob([this, event]() {
311 LoopOnce(event);
312 }, delayUs);
313 }
314 } // namespace Media
315 } // namespace OHOS