1 /*
2 * Copyright (c) 2023-2023 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 
17 #define HST_LOG_TAG "MediaSyncManager"
18 
19 #include "media_sync_manager.h"
20 #include <algorithm>
21 #include <cmath>
22 #include "common/log.h"
23 #include "osal/utils/steady_clock.h"
24 
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "MediaSyncManager" };
27 constexpr int64_t US_TO_MS = 1000; // 1000 us per ms
28 }
29 
30 namespace OHOS {
31 namespace Media {
32 namespace Pipeline {
33 namespace {
34 using namespace std::chrono;
35 constexpr int MEDIA_TUPLE_START_INDEX = 1;
36 constexpr int MEDIA_TUPLE_END_INDEX = 2;
37 }
38 
~MediaSyncManager()39 MediaSyncManager::~MediaSyncManager()
40 {
41     MEDIA_LOG_D_SHORT("~MediaSyncManager enter.");
42 }
43 
AddSynchronizer(IMediaSynchronizer* syncer)44 void MediaSyncManager::AddSynchronizer(IMediaSynchronizer* syncer)
45 {
46     if (syncer != nullptr) {
47         OHOS::Media::AutoLock lock(syncersMutex_);
48         if (std::find(syncers_.begin(), syncers_.end(), syncer) != syncers_.end()) {
49             return;
50         }
51         syncers_.emplace_back(syncer);
52     }
53 }
54 
RemoveSynchronizer(IMediaSynchronizer* syncer)55 void MediaSyncManager::RemoveSynchronizer(IMediaSynchronizer* syncer)
56 {
57     if (syncer != nullptr) {
58         OHOS::Media::AutoLock lock(syncersMutex_);
59         auto ite = std::find(syncers_.begin(), syncers_.end(), syncer);
60         if (ite != syncers_.end()) {
61             syncers_.erase(ite);
62         }
63     }
64 }
65 
SetPlaybackRate(float rate)66 Status MediaSyncManager::SetPlaybackRate(float rate)
67 {
68     if (rate < 0) {
69         return Status::ERROR_INVALID_PARAMETER;
70     }
71     OHOS::Media::AutoLock lock(clockMutex_);
72     MEDIA_LOG_I_SHORT("set play rate " PUBLIC_LOG_F, rate);
73     if (currentAbsMediaTime_ == HST_TIME_NONE || currentAnchorClockTime_ == HST_TIME_NONE
74         || currentAnchorMediaTime_ == HST_TIME_NONE || delayTime_ == HST_TIME_NONE) {
75         SimpleUpdatePlayRate(rate);
76         return Status::OK;
77     }
78     int64_t now = GetSystemClock();
79     int64_t currentMedia = SimpleGetMediaTimeExactly(currentAnchorClockTime_, delayTime_, now,
80         currentAnchorMediaTime_, playRate_);
81     int64_t currentAbsMedia = SimpleGetMediaTimeExactly(currentAnchorClockTime_, delayTime_, now,
82         currentAbsMediaTime_, playRate_);
83     SimpleUpdateTimeAnchor(now, currentMedia, currentAbsMedia);
84     SimpleUpdatePlayRate(rate);
85     return Status::OK;
86 }
87 
GetPlaybackRate()88 float MediaSyncManager::GetPlaybackRate()
89 {
90     OHOS::Media::AutoLock lock(clockMutex_);
91     return playRate_;
92 }
93 
SetMediaTimeStartEnd(int32_t trackId, int32_t index, int64_t val)94 void MediaSyncManager::SetMediaTimeStartEnd(int32_t trackId, int32_t index, int64_t val)
95 {
96     auto target = std::find_if(trackMediaTimeRange_.begin(), trackMediaTimeRange_.end(), [&trackId]
97         (const std::tuple<int32_t, int64_t, int64_t>& item) -> bool {
98             return std::get<0>(item) == trackId;
99         });
100     if (target == trackMediaTimeRange_.end()) {
101         trackMediaTimeRange_.emplace_back(std::tuple<int32_t, int64_t, int64_t>(trackId,
102             HST_TIME_NONE, HST_TIME_NONE));
103         if (index == MEDIA_TUPLE_START_INDEX) {
104             std::get<MEDIA_TUPLE_START_INDEX>(*trackMediaTimeRange_.rbegin()) = val;
105         } else if (index == MEDIA_TUPLE_END_INDEX) {
106             std::get<MEDIA_TUPLE_END_INDEX>(*trackMediaTimeRange_.rbegin()) = val;
107         } else {
108             MEDIA_LOG_W_SHORT("invalid index");
109         }
110     } else {
111         if (index == MEDIA_TUPLE_START_INDEX) {
112             std::get<MEDIA_TUPLE_START_INDEX>(*target) = val;
113         } else if (index == MEDIA_TUPLE_END_INDEX) {
114             std::get<MEDIA_TUPLE_END_INDEX>(*target) = val;
115         } else {
116             MEDIA_LOG_W_SHORT("invalid index");
117         }
118     }
119 }
120 
SetMediaTimeRangeStart(int64_t startMediaTime, int32_t trackId, IMediaSynchronizer* supplier)121 void MediaSyncManager::SetMediaTimeRangeStart(int64_t startMediaTime, int32_t trackId, IMediaSynchronizer* supplier)
122 {
123     if (!IsSupplierValid(supplier) || supplier->GetPriority() < currentRangeStartPriority_) {
124         return;
125     }
126     currentRangeStartPriority_ = supplier->GetPriority();
127     OHOS::Media::AutoLock lock(clockMutex_);
128     SetMediaTimeStartEnd(trackId, MEDIA_TUPLE_START_INDEX, startMediaTime);
129     if (minRangeStartOfMediaTime_ == HST_TIME_NONE || startMediaTime < minRangeStartOfMediaTime_) {
130         minRangeStartOfMediaTime_ = startMediaTime;
131         MEDIA_LOG_I_SHORT("set media started at " PUBLIC_LOG_D64, minRangeStartOfMediaTime_);
132     }
133 }
134 
SetMediaTimeRangeEnd(int64_t endMediaTime, int32_t trackId, IMediaSynchronizer* supplier)135 void MediaSyncManager::SetMediaTimeRangeEnd(int64_t endMediaTime, int32_t trackId, IMediaSynchronizer* supplier)
136 {
137     if (!IsSupplierValid(supplier) || supplier->GetPriority() < currentRangeEndPriority_) {
138         return;
139     }
140     currentRangeEndPriority_ = supplier->GetPriority();
141     OHOS::Media::AutoLock lock(clockMutex_);
142     SetMediaTimeStartEnd(trackId, MEDIA_TUPLE_END_INDEX, endMediaTime);
143     if (maxRangeEndOfMediaTime_ == HST_TIME_NONE || endMediaTime > maxRangeEndOfMediaTime_) {
144         maxRangeEndOfMediaTime_ = endMediaTime;
145         MEDIA_LOG_I_SHORT("set media end at " PUBLIC_LOG_D64, maxRangeEndOfMediaTime_);
146     }
147 }
148 
WaitAllPrerolled(bool prerolled)149 void MediaSyncManager::WaitAllPrerolled(bool prerolled)
150 {
151     allSyncerShouldPrerolled_ = prerolled;
152 }
153 
SetAllSyncShouldWaitNoLock()154 void MediaSyncManager::SetAllSyncShouldWaitNoLock()
155 {
156     if (allSyncerShouldPrerolled_ && !alreadySetSyncersShouldWait_) {
157         prerolledSyncers_.clear();
158         {
159             OHOS::Media::AutoLock lock1(syncersMutex_);
160             if (syncers_.size() > 1) {
161                 for (const auto &supplier: syncers_) {
162                     supplier->WaitAllPrerolled(true);
163                 }
164             }
165         }
166         alreadySetSyncersShouldWait_ = true;
167     }
168 }
169 
Resume()170 Status MediaSyncManager::Resume()
171 {
172     OHOS::Media::AutoLock lock(clockMutex_);
173     // update time anchor after a pause during normal playing
174     if (clockState_ == State::PAUSED && pausedExactAbsMediaTime_ != HST_TIME_NONE
175         && pausedExactMediaTime_ != HST_TIME_NONE && alreadySetSyncersShouldWait_) {
176         SimpleUpdateTimeAnchor(GetSystemClock(), pausedExactMediaTime_, pausedExactAbsMediaTime_);
177         pausedMediaTime_ = HST_TIME_NONE;
178         pausedExactMediaTime_ = HST_TIME_NONE;
179         pausedClockTime_ = HST_TIME_NONE;
180         pausedAbsMediaTime_ = HST_TIME_NONE;
181         pausedExactAbsMediaTime_ = HST_TIME_NONE;
182     }
183     if (clockState_ == State::RESUMED) {
184         return Status::OK;
185     }
186     SetAllSyncShouldWaitNoLock();
187     MEDIA_LOG_I_SHORT("resume");
188     clockState_ = State::RESUMED;
189     return Status::OK;
190 }
191 
GetSystemClock()192 int64_t MediaSyncManager::GetSystemClock()
193 {
194     return Plugins::HstTime2Us(SteadyClock::GetCurrentTimeNanoSec());
195 }
196 
Pause()197 Status MediaSyncManager::Pause()
198 {
199     OHOS::Media::AutoLock lock(clockMutex_);
200     if (clockState_ == State::PAUSED) {
201         return Status::OK;
202     }
203     pausedClockTime_ = GetSystemClock();
204     if (currentAnchorMediaTime_ != HST_TIME_NONE && currentAnchorClockTime_ != HST_TIME_NONE) {
205         pausedMediaTime_ = SimpleGetMediaTime(currentAnchorClockTime_, delayTime_, pausedClockTime_,
206             currentAnchorMediaTime_, playRate_);
207         pausedExactMediaTime_ = SimpleGetMediaTimeExactly(currentAnchorClockTime_, delayTime_, pausedClockTime_,
208             currentAnchorMediaTime_, playRate_);
209         pausedAbsMediaTime_ = SimpleGetMediaTime(currentAnchorClockTime_, delayTime_, pausedClockTime_,
210             currentAbsMediaTime_, playRate_);
211         pausedExactAbsMediaTime_ = SimpleGetMediaTimeExactly(currentAnchorClockTime_, delayTime_, pausedClockTime_,
212             currentAbsMediaTime_, playRate_);
213     } else {
214         pausedMediaTime_ = HST_TIME_NONE;
215         pausedExactMediaTime_ = HST_TIME_NONE;
216         pausedAbsMediaTime_ = HST_TIME_NONE;
217         pausedExactAbsMediaTime_ = HST_TIME_NONE;
218     }
219     pausedMediaTime_ = ClipMediaTime(pausedMediaTime_);
220     pausedExactMediaTime_ = ClipMediaTime(pausedExactMediaTime_);
221     pausedAbsMediaTime_ = ClipMediaTime(pausedAbsMediaTime_);
222     pausedExactAbsMediaTime_ = ClipMediaTime(pausedExactAbsMediaTime_);
223     MEDIA_LOG_I_SHORT("pause with clockTime " PUBLIC_LOG_D64 ", mediaTime " PUBLIC_LOG_D64 ", exactMediaTime "
224         PUBLIC_LOG_D64, pausedClockTime_, pausedAbsMediaTime_, pausedExactAbsMediaTime_);
225     clockState_ = State::PAUSED;
226     return Status::OK;
227 }
228 
Seek(int64_t mediaTime, bool isClosest)229 Status MediaSyncManager::Seek(int64_t mediaTime, bool isClosest)
230 {
231     OHOS::Media::AutoLock lock(clockMutex_);
232     if (minRangeStartOfMediaTime_ == HST_TIME_NONE || maxRangeEndOfMediaTime_ == HST_TIME_NONE) {
233         return Status::ERROR_INVALID_OPERATION;
234     }
235     isSeeking_ = true;
236     MEDIA_LOG_I_SHORT("isSeeking_ mediaTime: %{public}" PRId64, mediaTime);
237     seekingMediaTime_ = mediaTime;
238     alreadySetSyncersShouldWait_ = false; // set already as false
239     SetAllSyncShouldWaitNoLock(); // all suppliers should sync preroll again after seek
240     ResetTimeAnchorNoLock(); // reset the time anchor
241     frameAfterSeeked_ = true;
242     if (isClosest) {
243         firstMediaTimeAfterSeek_ = mediaTime;
244     } else {
245         firstMediaTimeAfterSeek_ = HST_TIME_NONE;
246     }
247     return Status::OK;
248 }
249 
Reset()250 Status MediaSyncManager::Reset()
251 {
252     MEDIA_LOG_I_SHORT("do Reset");
253     Stop();
254     {
255         OHOS::Media::AutoLock lock1(syncersMutex_);
256         syncers_.clear();
257         prerolledSyncers_.clear();
258     }
259     frameAfterSeeked_ = false;
260     lastReportMediaTime_ = HST_TIME_NONE;
261     firstMediaTimeAfterSeek_ = HST_TIME_NONE;
262     return Status::OK;
263 }
264 
Stop()265 Status MediaSyncManager::Stop()
266 {
267     MEDIA_LOG_I_SHORT("do Stop");
268     OHOS::Media::AutoLock lock(clockMutex_);
269     clockState_ = State::PAUSED;
270     ResetTimeAnchorNoLock();
271     pausedClockTime_ = HST_TIME_NONE;
272     playRate_ = 1.0f;
273     alreadySetSyncersShouldWait_ = false;
274     allSyncerShouldPrerolled_ = true;
275     isSeeking_ = false;
276     seekCond_.notify_all();
277     seekingMediaTime_ = HST_TIME_NONE;
278     trackMediaTimeRange_.clear();
279     minRangeStartOfMediaTime_ = HST_TIME_NONE;
280     maxRangeEndOfMediaTime_ = HST_TIME_NONE;
281 
282     return Status::OK;
283 }
284 
ClipMediaTime(int64_t inTime)285 int64_t MediaSyncManager::ClipMediaTime(int64_t inTime)
286 {
287     int64_t ret = inTime;
288     if (minRangeStartOfMediaTime_ != HST_TIME_NONE && ret < minRangeStartOfMediaTime_) {
289         ret = minRangeStartOfMediaTime_;
290         MEDIA_LOG_D_SHORT("clip to min media time " PUBLIC_LOG_D64, ret);
291     }
292     if (maxRangeEndOfMediaTime_ != HST_TIME_NONE && ret > maxRangeEndOfMediaTime_) {
293         ret = maxRangeEndOfMediaTime_;
294         MEDIA_LOG_D_SHORT("clip to max media time " PUBLIC_LOG_D64, ret);
295     }
296     return ret;
297 }
298 
ResetTimeAnchorNoLock()299 void MediaSyncManager::ResetTimeAnchorNoLock()
300 {
301     pausedMediaTime_ = HST_TIME_NONE;
302     pausedExactMediaTime_ = HST_TIME_NONE;
303     pausedAbsMediaTime_ = HST_TIME_NONE;
304     pausedExactAbsMediaTime_ = HST_TIME_NONE;
305     currentSyncerPriority_ = IMediaSynchronizer::NONE;
306     SimpleUpdateTimeAnchor(HST_TIME_NONE, HST_TIME_NONE, HST_TIME_NONE);
307 }
308 
SimpleUpdatePlayRate(float playRate)309 void MediaSyncManager::SimpleUpdatePlayRate(float playRate)
310 {
311     playRate_ = playRate;
312 }
313 
SimpleUpdateTimeAnchor(int64_t clockTime, int64_t mediaTime, int64_t mediaAbsTime)314 void MediaSyncManager::SimpleUpdateTimeAnchor(int64_t clockTime, int64_t mediaTime, int64_t mediaAbsTime)
315 {
316     currentAnchorMediaTime_ = mediaTime;
317     currentAnchorClockTime_ = clockTime;
318     currentAbsMediaTime_ = mediaAbsTime;
319 }
320 
IsSupplierValid(IMediaSynchronizer* supplier)321 bool MediaSyncManager::IsSupplierValid(IMediaSynchronizer* supplier)
322 {
323     OHOS::Media::AutoLock lock(syncersMutex_);
324     return std::find(syncers_.begin(), syncers_.end(), supplier) != syncers_.end();
325 }
326 
UpdateFirstPtsAfterSeek(int64_t mediaTime)327 void MediaSyncManager::UpdateFirstPtsAfterSeek(int64_t mediaTime)
328 {
329     if (firstMediaTimeAfterSeek_ == HST_TIME_NONE) {
330         firstMediaTimeAfterSeek_ = mediaTime;
331         return;
332     }
333     if (mediaTime > firstMediaTimeAfterSeek_) {
334         firstMediaTimeAfterSeek_ = mediaTime;
335     }
336 }
337 
UpdateTimeAnchor(int64_t clockTime, int64_t delayTime, IMediaTime iMediaTime, IMediaSynchronizer* supplier)338 bool MediaSyncManager::UpdateTimeAnchor(int64_t clockTime, int64_t delayTime, IMediaTime iMediaTime,
339     IMediaSynchronizer* supplier)
340 {
341     OHOS::Media::AutoLock lock(clockMutex_);
342     bool render = true;
343     if (clockTime == HST_TIME_NONE || iMediaTime.mediaTime == HST_TIME_NONE
344         || delayTime == HST_TIME_NONE || supplier == nullptr) {
345         return render;
346     }
347     clockTime += delayTime;
348     delayTime_ = delayTime;
349     if (IsSupplierValid(supplier) && supplier->GetPriority() >= currentSyncerPriority_) {
350         currentSyncerPriority_ = supplier->GetPriority();
351         SimpleUpdateTimeAnchor(clockTime, iMediaTime.mediaTime, iMediaTime.absMediaTime);
352         MEDIA_LOG_D_SHORT("update time anchor to priority " PUBLIC_LOG_D32 ", mediaTime " PUBLIC_LOG_D64 ", clockTime "
353         PUBLIC_LOG_D64, currentSyncerPriority_, currentAnchorMediaTime_, currentAnchorClockTime_);
354         if (isSeeking_) {
355             MEDIA_LOG_I_SHORT("leaving seeking_");
356             isSeeking_ = false;
357             UpdateFirstPtsAfterSeek(iMediaTime.mediaTime);
358             seekCond_.notify_all();
359         }
360     }
361     return render;
362 }
363 
SimpleGetMediaTime(int64_t anchorClockTime, int64_t delayTime, int64_t nowClockTime, int64_t anchorMediaTime, float playRate)364 int64_t MediaSyncManager::SimpleGetMediaTime(int64_t anchorClockTime, int64_t delayTime, int64_t nowClockTime,
365     int64_t anchorMediaTime, float playRate)
366 {
367     if (std::fabs(playRate - 0) < 1e-9) { // 0 threshold
368         return HST_TIME_NONE;
369     }
370     if (anchorClockTime == HST_TIME_NONE || nowClockTime == HST_TIME_NONE
371         || anchorMediaTime == HST_TIME_NONE || delayTime== HST_TIME_NONE) {
372         return HST_TIME_NONE;
373     }
374     return anchorMediaTime;
375 }
376 
SimpleGetMediaTimeExactly(int64_t anchorClockTime, int64_t delayTime, int64_t nowClockTime, int64_t anchorMediaTime, float playRate)377 int64_t MediaSyncManager::SimpleGetMediaTimeExactly(int64_t anchorClockTime, int64_t delayTime, int64_t nowClockTime,
378     int64_t anchorMediaTime, float playRate)
379 {
380     if (std::fabs(playRate - 0) < 1e-9) { // 0 threshold
381         return HST_TIME_NONE;
382     }
383     if (anchorClockTime == HST_TIME_NONE || nowClockTime == HST_TIME_NONE
384         || anchorMediaTime == HST_TIME_NONE || delayTime== HST_TIME_NONE) {
385         return HST_TIME_NONE;
386     }
387     return anchorMediaTime + (nowClockTime - anchorClockTime + delayTime) * static_cast<double>(playRate) - delayTime;
388 }
389 
SetLastAudioBufferDuration(int64_t durationUs)390 void MediaSyncManager::SetLastAudioBufferDuration(int64_t durationUs)
391 {
392     if (durationUs > 0) {
393         lastAudioBufferDuration_ = durationUs;
394     } else {
395         lastAudioBufferDuration_ = 0; // If buffer duration is unavailable, treat it as 0.
396     }
397 }
398 
SetLastVideoBufferPts(int64_t bufferPts)399 void MediaSyncManager::SetLastVideoBufferPts(int64_t bufferPts)
400 {
401     lastVideoBufferPts_ = bufferPts;
402 }
403 
ReportLagEvent(int64_t lagDurationMs)404 void MediaSyncManager::ReportLagEvent(int64_t lagDurationMs)
405 {
406     auto eventReceiver = eventReceiver_.lock();
407     FALSE_RETURN(eventReceiver != nullptr);
408     eventReceiver->OnEvent({"SyncManager", EventType::EVENT_STREAM_LAG, lagDurationMs});
409 }
410 
BoundMediaProgress(int64_t newMediaProgressTime)411 int64_t MediaSyncManager::BoundMediaProgress(int64_t newMediaProgressTime)
412 {
413     int64_t maxMediaProgress = 0;
414     if (currentSyncerPriority_ == IMediaSynchronizer::AUDIO_SINK) {
415         maxMediaProgress = currentAnchorMediaTime_ + lastAudioBufferDuration_;
416     } else if (currentSyncerPriority_ == IMediaSynchronizer::VIDEO_SINK) {
417         maxMediaProgress = lastVideoBufferPts_;
418     } else {
419         maxMediaProgress = currentAnchorMediaTime_;
420     }
421     if (newMediaProgressTime > maxMediaProgress) {
422         ReportLagEvent((newMediaProgressTime - maxMediaProgress) / US_TO_MS);
423         lastReportMediaTime_ = maxMediaProgress; // Avoid media progress go too far when data underrun.
424         MEDIA_LOG_W("Data underrun for %{public}" PRId64 " us, currentSyncerPriority_ is %{public}" PRId32,
425             newMediaProgressTime - maxMediaProgress, currentSyncerPriority_);
426         return lastReportMediaTime_;
427     }
428     if ((newMediaProgressTime >= lastReportMediaTime_) || frameAfterSeeked_) {
429         lastReportMediaTime_ = newMediaProgressTime;
430     } else {
431         MEDIA_LOG_W_SHORT("Avoid media time to go back without seek, from %{public}" PRId64 " to %{public}" PRId64,
432             lastReportMediaTime_.load(), newMediaProgressTime);
433     }
434     frameAfterSeeked_ = false;
435     return lastReportMediaTime_;
436 }
437 
GetMediaTimeNow()438 int64_t MediaSyncManager::GetMediaTimeNow()
439 {
440     OHOS::Media::AutoLock lock(clockMutex_);
441     if (isSeeking_) {
442         // no need to bound media progress during seek
443         MEDIA_LOG_D_SHORT("GetMediaTimeNow seekingMediaTime_: %{public}" PRId64, seekingMediaTime_);
444         return seekingMediaTime_;
445     }
446     int64_t currentMediaTime;
447     if (clockState_ == State::PAUSED) {
448         currentMediaTime = pausedExactAbsMediaTime_;
449     } else {
450         currentMediaTime = SimpleGetMediaTimeExactly(currentAnchorClockTime_, delayTime_, GetSystemClock(),
451             currentAbsMediaTime_, playRate_);
452     }
453     if (currentMediaTime == HST_TIME_NONE) {
454         return 0;
455     }
456     if (firstMediaTimeAfterSeek_ != HST_TIME_NONE && currentMediaTime < firstMediaTimeAfterSeek_) {
457         MEDIA_LOG_W_SHORT("audio has not been rendered since seek");
458         currentMediaTime = firstMediaTimeAfterSeek_;
459     }
460     if (startPts_ != HST_TIME_NONE) {
461         currentMediaTime -= startPts_;
462     }
463     currentMediaTime = BoundMediaProgress(currentMediaTime);
464     MEDIA_LOG_D_SHORT("GetMediaTimeNow currentMediaTime: %{public}" PRId64, currentMediaTime);
465     return currentMediaTime;
466 }
467 
GetClockTimeNow()468 int64_t MediaSyncManager::GetClockTimeNow()
469 {
470     {
471         OHOS::Media::AutoLock lock(clockMutex_);
472         if (clockState_ == State::PAUSED) {
473             return pausedClockTime_;
474         }
475     }
476     return GetSystemClock();
477 }
SimpleGetClockTime(int64_t anchorClockTime, int64_t nowMediaTime, int64_t anchorMediaTime, float playRate)478 int64_t MediaSyncManager::SimpleGetClockTime(int64_t anchorClockTime, int64_t nowMediaTime,
479     int64_t anchorMediaTime, float playRate)
480 {
481     if (std::fabs(playRate - 0) < 1e-9) { // 0 threshold
482         return HST_TIME_NONE;
483     }
484     if (anchorClockTime == HST_TIME_NONE || nowMediaTime == HST_TIME_NONE || anchorMediaTime == HST_TIME_NONE) {
485         return HST_TIME_NONE;
486     }
487     return anchorClockTime + (nowMediaTime - anchorMediaTime) / static_cast<double>(playRate);
488 }
489 
GetClockTime(int64_t mediaTime)490 int64_t MediaSyncManager::GetClockTime(int64_t mediaTime)
491 {
492     OHOS::Media::AutoLock lock(clockMutex_);
493     if (minRangeStartOfMediaTime_ != HST_TIME_NONE && mediaTime < minRangeStartOfMediaTime_) {
494         MEDIA_LOG_D_SHORT("media time " PUBLIC_LOG_D64 " less than min media time " PUBLIC_LOG_D64,
495                 mediaTime, minRangeStartOfMediaTime_);
496     }
497     if (maxRangeEndOfMediaTime_ != HST_TIME_NONE && mediaTime > maxRangeEndOfMediaTime_) {
498         MEDIA_LOG_D_SHORT("media time " PUBLIC_LOG_D64 " exceed max media time " PUBLIC_LOG_D64,
499                 mediaTime, maxRangeEndOfMediaTime_);
500     }
501     return SimpleGetClockTime(currentAnchorClockTime_, mediaTime, currentAnchorMediaTime_, playRate_);
502 }
503 
ReportPrerolled(IMediaSynchronizer* supplier)504 void MediaSyncManager::ReportPrerolled(IMediaSynchronizer* supplier)
505 {
506     if (supplier == nullptr) {
507         return;
508     }
509     if (!allSyncerShouldPrerolled_) {
510         return;
511     }
512     OHOS::Media::AutoLock lock(syncersMutex_);
513     auto ite = std::find(prerolledSyncers_.begin(), prerolledSyncers_.end(), supplier);
514     if (ite != prerolledSyncers_.end()) {
515         MEDIA_LOG_I_SHORT("supplier already reported prerolled");
516         return;
517     }
518     prerolledSyncers_.emplace_back(supplier);
519     if (prerolledSyncers_.size() == syncers_.size()) {
520         for (const auto& prerolled : prerolledSyncers_) {
521             prerolled->NotifyAllPrerolled();
522         }
523         prerolledSyncers_.clear();
524     }
525 }
526 
GetSeekTime()527 int64_t MediaSyncManager::GetSeekTime()
528 {
529     return seekingMediaTime_;
530 }
531 
InSeeking()532 bool MediaSyncManager::InSeeking()
533 {
534     return isSeeking_;
535 }
536 
SetMediaStartPts(int64_t startPts)537 void MediaSyncManager::SetMediaStartPts(int64_t startPts)
538 {
539     if (startPts_ == HST_TIME_NONE || startPts < startPts_) {
540         startPts_ = startPts;
541     }
542 }
543 
ResetMediaStartPts()544 void MediaSyncManager::ResetMediaStartPts()
545 {
546     startPts_ = HST_TIME_NONE;
547 }
548 
GetMediaStartPts()549 int64_t MediaSyncManager::GetMediaStartPts()
550 {
551     return startPts_;
552 }
553 
ReportEos(IMediaSynchronizer* supplier)554 void MediaSyncManager::ReportEos(IMediaSynchronizer* supplier)
555 {
556     if (supplier == nullptr) {
557         return;
558     }
559     OHOS::Media::AutoLock lock(clockMutex_);
560     if (IsSupplierValid(supplier) && supplier->GetPriority() >= currentSyncerPriority_) {
561         currentSyncerPriority_ = IMediaSynchronizer::NONE;
562         if (isSeeking_) {
563             MEDIA_LOG_I_SHORT("reportEos leaving seeking_");
564             isSeeking_ = false;
565             seekCond_.notify_all();
566         }
567     }
568 }
569 
SetEventReceiver(std::weak_ptr<EventReceiver> eventReceiver)570 void MediaSyncManager::SetEventReceiver(std::weak_ptr<EventReceiver> eventReceiver)
571 {
572     eventReceiver_ = eventReceiver;
573 }
574 } // namespace Pipeline
575 } // namespace Media
576 } // namespace OHOS