• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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