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