1 /*
2  * Copyright (C) 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 #include "audio_sink.h"
17 #include "syspara/parameters.h"
18 #include "plugin/plugin_manager_v2.h"
19 #include "common/log.h"
20 #include "calc_max_amplitude.h"
21 
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "AudioSink" };
24 constexpr int64_t MAX_BUFFER_DURATION_US = 200000; // Max buffer duration is 200 ms
25 constexpr int64_t US_TO_MS = 1000; // 1000 us per ms
26 constexpr int64_t ANCHOR_UPDATE_PERIOD_US = 200000; // Update time anchor every 200 ms
27 constexpr int64_t DRAIN_TIME_DIFF_WARN_MS = 40;
28 constexpr int64_t DRAIN_TIME_DIFF_INFO_MS = 20;
29 constexpr int64_t AUDIO_SAMPLE_8_BIT = 1;
30 constexpr int64_t AUDIO_SAMPLE_16_BIT = 2;
31 constexpr int64_t AUDIO_SAMPLE_24_BIT = 3;
32 constexpr int64_t AUDIO_SAMPLE_32_BIT = 4;
33 }
34 
35 namespace OHOS {
36 namespace Media {
37 
38 const int32_t DEFAULT_BUFFER_QUEUE_SIZE = 8;
39 const int32_t APE_BUFFER_QUEUE_SIZE = 32;
40 const int64_t DEFAULT_PLAY_RANGE_VALUE = -1;
41 const int64_t MICROSECONDS_CONVERT_UNITS = 1000;
42 
GetAudioLatencyFixDelay()43 int64_t GetAudioLatencyFixDelay()
44 {
45     constexpr uint64_t defaultValue = 120 * HST_USECOND;
46     static uint64_t fixDelay = OHOS::system::GetUintParameter("debug.media_service.audio_sync_fix_delay", defaultValue);
47     MEDIA_LOG_I("audio_sync_fix_delay, pid:%{public}d, fixdelay: " PUBLIC_LOG_U64, getprocpid(), fixDelay);
48     return static_cast<int64_t>(fixDelay);
49 }
50 
AudioSink()51 AudioSink::AudioSink()
52 {
53     MEDIA_LOG_I("AudioSink ctor");
54     syncerPriority_ = IMediaSynchronizer::AUDIO_SINK;
55     fixDelay_ = GetAudioLatencyFixDelay();
56     plugin_ = CreatePlugin();
57 }
58 
~AudioSink()59 AudioSink::~AudioSink()
60 {
61     MEDIA_LOG_I("AudioSink dtor");
62 }
63 
Init(std::shared_ptr<Meta> & meta,const std::shared_ptr<Pipeline::EventReceiver> & receiver)64 Status AudioSink::Init(std::shared_ptr<Meta>& meta, const std::shared_ptr<Pipeline::EventReceiver>& receiver)
65 {
66     state_ = Pipeline::FilterState::INITIALIZED;
67     FALSE_RETURN_V(plugin_ != nullptr, Status::ERROR_NULL_POINTER);
68     if (meta != nullptr) {
69         meta->SetData(Tag::APP_PID, appPid_);
70         meta->SetData(Tag::APP_UID, appUid_);
71     }
72     plugin_->SetEventReceiver(receiver);
73     plugin_->SetParameter(meta);
74     plugin_->Init();
75     plugin_->Prepare();
76     plugin_->SetMuted(isMuted_);
77     meta->GetData(Tag::AUDIO_SAMPLE_RATE, sampleRate_);
78     meta->GetData(Tag::AUDIO_SAMPLE_PER_FRAME, samplePerFrame_);
79     meta->GetData(Tag::AUDIO_CHANNEL_COUNT, audioChannelCount_);
80     if (samplePerFrame_ > 0 && sampleRate_ > 0) {
81         playingBufferDurationUs_ = samplePerFrame_ * 1000000 / sampleRate_; // 1000000 usec per sec
82     }
83     MEDIA_LOG_I("Audiosink playingBufferDurationUs_ = " PUBLIC_LOG_D64, playingBufferDurationUs_);
84     std::string mime;
85     bool mimeGetRes = meta->Get<Tag::MIME_TYPE>(mime);
86     if (mimeGetRes && mime == "audio/x-ape") {
87         isApe_ = true;
88         MEDIA_LOG_I("AudioSink::Init is ape");
89     }
90 
91     return Status::OK;
92 }
93 
GetBufferQueueProducer()94 sptr<AVBufferQueueProducer> AudioSink::GetBufferQueueProducer()
95 {
96     if (state_ != Pipeline::FilterState::READY) {
97         return nullptr;
98     }
99     return inputBufferQueueProducer_;
100 }
101 
GetBufferQueueConsumer()102 sptr<AVBufferQueueConsumer> AudioSink::GetBufferQueueConsumer()
103 {
104     if (state_ != Pipeline::FilterState::READY) {
105         return nullptr;
106     }
107     return inputBufferQueueConsumer_;
108 }
109 
SetParameter(const std::shared_ptr<Meta> & meta)110 Status AudioSink::SetParameter(const std::shared_ptr<Meta>& meta)
111 {
112     UpdateMediaTimeRange(meta);
113     if (meta != nullptr) {
114         meta->GetData(Tag::APP_PID, appPid_);
115         meta->GetData(Tag::APP_UID, appUid_);
116     }
117     FALSE_RETURN_V(plugin_ != nullptr, Status::ERROR_NULL_POINTER);
118     plugin_->SetParameter(meta);
119     return Status::OK;
120 }
121 
GetParameter(std::shared_ptr<Meta> & meta)122 Status AudioSink::GetParameter(std::shared_ptr<Meta>& meta)
123 {
124     return plugin_->GetParameter(meta);
125 }
126 
Prepare()127 Status AudioSink::Prepare()
128 {
129     state_ = Pipeline::FilterState::PREPARING;
130     Status ret = PrepareInputBufferQueue();
131     if (ret != Status::OK) {
132         state_ = Pipeline::FilterState::INITIALIZED;
133         return ret;
134     }
135     state_ = Pipeline::FilterState::READY;
136     {
137         AutoLock lock(eosMutex_);
138         eosInterruptType_ = EosInterruptState::NONE;
139         eosDraining_ = false;
140     }
141     return ret;
142 }
143 
Start()144 Status AudioSink::Start()
145 {
146     Status ret = plugin_->Start();
147     if (ret != Status::OK) {
148         MEDIA_LOG_I("AudioSink start error " PUBLIC_LOG_D32, ret);
149         return ret;
150     }
151     isEos_ = false;
152     state_ = Pipeline::FilterState::RUNNING;
153     return ret;
154 }
155 
Stop()156 Status AudioSink::Stop()
157 {
158     playRangeStartTime_ = DEFAULT_PLAY_RANGE_VALUE;
159     playRangeEndTime_ = DEFAULT_PLAY_RANGE_VALUE;
160     Status ret = plugin_->Stop();
161     underrunDetector_.Reset();
162     lagDetector_.Reset();
163     forceUpdateTimeAnchorNextTime_ = true;
164     if (ret != Status::OK) {
165         return ret;
166     }
167     state_ = Pipeline::FilterState::INITIALIZED;
168     AutoLock lock(eosMutex_);
169     if (eosInterruptType_ != EosInterruptState::NONE) {
170         eosInterruptType_ = EosInterruptState::STOP;
171     }
172     return ret;
173 }
174 
Pause()175 Status AudioSink::Pause()
176 {
177     Status ret = Status::OK;
178     underrunDetector_.Reset();
179     lagDetector_.Reset();
180     if (isTransitent_ || isEos_) {
181         ret = plugin_->PauseTransitent();
182     } else {
183         ret = plugin_->Pause();
184     }
185     forceUpdateTimeAnchorNextTime_ = true;
186     if (ret != Status::OK) {
187         return ret;
188     }
189     state_ = Pipeline::FilterState::PAUSED;
190     AutoLock lock(eosMutex_);
191     if (eosInterruptType_ == EosInterruptState::INITIAL || eosInterruptType_ == EosInterruptState::RESUME) {
192         eosInterruptType_ = EosInterruptState::PAUSE;
193     }
194     return ret;
195 }
196 
Resume()197 Status AudioSink::Resume()
198 {
199     lagDetector_.Reset();
200     Status ret = plugin_->Resume();
201     if (ret != Status::OK) {
202         MEDIA_LOG_I("AudioSink resume error " PUBLIC_LOG_D32, ret);
203         return ret;
204     }
205     state_ = Pipeline::FilterState::RUNNING;
206     AutoLock lock(eosMutex_);
207     if (eosInterruptType_ == EosInterruptState::PAUSE) {
208         eosInterruptType_ = EosInterruptState::RESUME;
209         if (!eosDraining_ && eosTask_ != nullptr) {
210             eosTask_->SubmitJobOnce([this] {
211                 HandleEosInner(false);
212             });
213         }
214     }
215     return ret;
216 }
217 
Flush()218 Status AudioSink::Flush()
219 {
220     underrunDetector_.Reset();
221     lagDetector_.Reset();
222     {
223         AutoLock lock(eosMutex_);
224         eosInterruptType_ = EosInterruptState::NONE;
225         eosDraining_ = false;
226     }
227     forceUpdateTimeAnchorNextTime_ = true;
228     return plugin_->Flush();
229 }
230 
Release()231 Status AudioSink::Release()
232 {
233     underrunDetector_.Reset();
234     lagDetector_.Reset();
235     return plugin_->Deinit();
236 }
237 
SetPlayRange(int64_t start,int64_t end)238 Status AudioSink::SetPlayRange(int64_t start, int64_t end)
239 {
240     MEDIA_LOG_I("SetPlayRange enter.");
241     playRangeStartTime_ = start;
242     playRangeEndTime_ = end;
243     return Status::OK;
244 }
245 
SetVolume(float volume)246 Status AudioSink::SetVolume(float volume)
247 {
248     if (plugin_ == nullptr) {
249         return Status::ERROR_NULL_POINTER;
250     }
251     if (volume < 0) {
252         return Status::ERROR_INVALID_PARAMETER;
253     }
254     volume_ = volume;
255     return plugin_->SetVolume(volume);
256 }
257 
SetVolumeWithRamp(float targetVolume,int32_t duration)258 int32_t AudioSink::SetVolumeWithRamp(float targetVolume, int32_t duration)
259 {
260     MEDIA_LOG_I("AudioSink::SetVolumeWithRamp entered. ");
261     return plugin_->SetVolumeWithRamp(targetVolume, duration);
262 }
263 
SetIsTransitent(bool isTransitent)264 Status AudioSink::SetIsTransitent(bool isTransitent)
265 {
266     MEDIA_LOG_I("AudioSink::SetIsTransitent entered. ");
267     isTransitent_ = isTransitent;
268     return Status::OK;
269 }
270 
PrepareInputBufferQueue()271 Status AudioSink::PrepareInputBufferQueue()
272 {
273     if (inputBufferQueue_ != nullptr && inputBufferQueue_-> GetQueueSize() > 0) {
274         MEDIA_LOG_I("InputBufferQueue already create");
275         return Status::ERROR_INVALID_OPERATION;
276     }
277     int32_t inputBufferSize = isApe_ ? APE_BUFFER_QUEUE_SIZE : DEFAULT_BUFFER_QUEUE_SIZE;
278     MemoryType memoryType = MemoryType::SHARED_MEMORY;
279 #ifndef MEDIA_OHOS
280     memoryType = MemoryType::VIRTUAL_MEMORY;
281 #endif
282     MEDIA_LOG_I("PrepareInputBufferQueue ");
283     inputBufferQueue_ = AVBufferQueue::Create(inputBufferSize, memoryType, INPUT_BUFFER_QUEUE_NAME);
284     inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
285     inputBufferQueueConsumer_ = inputBufferQueue_->GetConsumer();
286     return Status::OK;
287 }
288 
CreatePlugin()289 std::shared_ptr<Plugins::AudioSinkPlugin> AudioSink::CreatePlugin()
290 {
291     auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByMime(Plugins::PluginType::AUDIO_SINK, "audio/raw");
292     if (plugin == nullptr) {
293         return nullptr;
294     }
295     return std::reinterpret_pointer_cast<Plugins::AudioSinkPlugin>(plugin);
296 }
297 
UpdateAudioWriteTimeMayWait()298 void AudioSink::UpdateAudioWriteTimeMayWait()
299 {
300     if (latestBufferDuration_ <= 0) {
301         return;
302     }
303     if (latestBufferDuration_ > MAX_BUFFER_DURATION_US) {
304         latestBufferDuration_ = MAX_BUFFER_DURATION_US; // wait at most MAX_DURATION
305     }
306     int64_t timeNow = Plugins::HstTime2Us(SteadyClock::GetCurrentTimeNanoSec());
307     if (!lastBufferWriteSuccess_) {
308         int64_t writeSleepTime = latestBufferDuration_ - (timeNow - lastBufferWriteTime_);
309         MEDIA_LOG_W("Last buffer write fail, sleep time is " PUBLIC_LOG_D64 "us", writeSleepTime);
310         if (writeSleepTime > 0) {
311             usleep(writeSleepTime);
312             timeNow = Plugins::HstTime2Us(SteadyClock::GetCurrentTimeNanoSec());
313         }
314     }
315     lastBufferWriteTime_ = timeNow;
316 }
317 
SetThreadGroupId(const std::string & groupId)318 void AudioSink::SetThreadGroupId(const std::string& groupId)
319 {
320     eosTask_ = std::make_unique<Task>("OS_EOSa", groupId, TaskType::AUDIO, TaskPriority::HIGH, false);
321 }
322 
HandleEosInner(bool drain)323 void AudioSink::HandleEosInner(bool drain)
324 {
325     AutoLock lock(eosMutex_);
326     eosDraining_ = true; // start draining task
327     switch (eosInterruptType_) {
328         case EosInterruptState::INITIAL: // No user operation during EOS drain, complete drain normally
329             break;
330         case EosInterruptState::RESUME: // EOS drain is resumed after pause, do necessary changes
331             if (drain) {
332                 // pause and resume happened before this task, audiosink latency should be updated
333                 drain = false;
334             }
335             eosInterruptType_ = EosInterruptState::INITIAL; // Reset EOS draining state
336             break;
337         default: // EOS drain is interrupted by pause or stop, and not resumed
338             MEDIA_LOG_W("Drain audiosink interrupted");
339             eosDraining_ = false; // abort draining task
340             return;
341     }
342     if (drain) {
343         MEDIA_LOG_I("Drain audiosink and report EOS");
344         DrainAndReportEosEvent();
345         return;
346     }
347     uint64_t latency = 0;
348     if (plugin_->GetLatency(latency) != Status::OK) {
349         MEDIA_LOG_W("Failed to get latency, drain audiosink directly");
350         DrainAndReportEosEvent();
351         return;
352     }
353     if (eosTask_ == nullptr) {
354         MEDIA_LOG_W("Drain audiosink, eosTask_ is nullptr");
355         DrainAndReportEosEvent();
356         return;
357     }
358     MEDIA_LOG_I("Drain audiosink wait latency = " PUBLIC_LOG_U64, latency);
359     eosTask_->SubmitJobOnce([this] {
360             HandleEosInner(true);
361         }, latency, false);
362 }
363 
DrainAndReportEosEvent()364 void AudioSink::DrainAndReportEosEvent()
365 {
366     plugin_->Drain();
367     plugin_->PauseTransitent();
368     eosInterruptType_ = EosInterruptState::NONE;
369     eosDraining_ = false; // finish draining task
370     isEos_ = true;
371     auto syncCenter = syncCenter_.lock();
372     if (syncCenter) {
373         syncCenter->ReportEos(this);
374     }
375     Event event {
376         .srcFilter = "AudioSink",
377         .type = EventType::EVENT_COMPLETE,
378     };
379     FALSE_RETURN(playerEventReceiver_ != nullptr);
380     playerEventReceiver_->OnEvent(event);
381 }
382 
DropApeBuffer(std::shared_ptr<AVBuffer> filledOutputBuffer)383 bool AudioSink::DropApeBuffer(std::shared_ptr<AVBuffer> filledOutputBuffer)
384 {
385     if (!isApe_ || seekTimeUs_ == HST_TIME_NONE) {
386         return false;
387     }
388     FALSE_RETURN_V(inputBufferQueueConsumer_ != nullptr, false);
389     if (filledOutputBuffer->pts_ < seekTimeUs_) {
390         MEDIA_LOG_D("Drop ape buffer pts = " PUBLIC_LOG_D64, filledOutputBuffer->pts_);
391         inputBufferQueueConsumer_->ReleaseBuffer(filledOutputBuffer);
392         return true;
393     } else {
394         seekTimeUs_ = HST_TIME_NONE;
395     }
396     return false;
397 }
CheckUpdateState(char * frame,uint64_t replyBytes,int32_t format)398 void AudioSink::CheckUpdateState(char *frame, uint64_t replyBytes, int32_t format)
399 {
400     FALSE_RETURN(frame != nullptr && replyBytes != 0);
401     auto currentMaxAmplitude = OHOS::Media::CalcMaxAmplitude::UpdateMaxAmplitude(frame, replyBytes, format);
402     AutoLock amplitudeLock(amplitudeMutex_);
403     if (currentMaxAmplitude > maxAmplitude_) {
404         maxAmplitude_ = currentMaxAmplitude;
405     }
406 }
407 
GetMaxAmplitude()408 float AudioSink::GetMaxAmplitude()
409 {
410     AutoLock amplitudeLock(amplitudeMutex_);
411     auto ret = maxAmplitude_;
412     maxAmplitude_ = 0;
413     return ret;
414 }
415 
CalcMaxAmplitude(std::shared_ptr<AVBuffer> filledOutputBuffer)416 void AudioSink::CalcMaxAmplitude(std::shared_ptr<AVBuffer> filledOutputBuffer)
417 {
418     FALSE_RETURN(filledOutputBuffer != nullptr);
419     auto mem = filledOutputBuffer->memory_;
420     FALSE_RETURN(mem != nullptr);
421     auto srcBuffer = mem->GetAddr();
422     auto destBuffer = const_cast<uint8_t *>(srcBuffer);
423     auto srcLength = mem->GetSize();
424     size_t destLength = static_cast<size_t>(srcLength);
425     int32_t format = plugin_->GetSampleFormat();
426     CheckUpdateState(reinterpret_cast<char *>(destBuffer), destLength, format);
427 }
428 
DrainOutputBuffer(bool flushed)429 void AudioSink::DrainOutputBuffer(bool flushed)
430 {
431     std::lock_guard<std::mutex> lock(pluginMutex_);
432     std::shared_ptr<AVBuffer> filledOutputBuffer = nullptr;
433     FALSE_RETURN(plugin_ != nullptr && inputBufferQueueConsumer_ != nullptr);
434     Status ret = inputBufferQueueConsumer_->AcquireBuffer(filledOutputBuffer);
435     FALSE_RETURN(ret == Status::OK && filledOutputBuffer != nullptr);
436     if (state_ != Pipeline::FilterState::RUNNING || flushed) {
437         MEDIA_LOG_E("Drop buffer pts = " PUBLIC_LOG_D64, filledOutputBuffer->pts_);
438         inputBufferQueueConsumer_->ReleaseBuffer(filledOutputBuffer);
439         return;
440     }
441     if ((filledOutputBuffer->flag_ & BUFFER_FLAG_EOS) ||
442         ((playRangeEndTime_ != DEFAULT_PLAY_RANGE_VALUE) &&
443         (filledOutputBuffer->pts_ > playRangeEndTime_ * MICROSECONDS_CONVERT_UNITS))) {
444         inputBufferQueueConsumer_->ReleaseBuffer(filledOutputBuffer);
445         AutoLock eosLock(eosMutex_);
446         // avoid submit handle eos task multiple times
447         FALSE_RETURN(!eosDraining_);
448         eosInterruptType_ = EosInterruptState::INITIAL;
449         if (eosTask_ == nullptr) {
450             DrainAndReportEosEvent();
451             return;
452         }
453         eosTask_->SubmitJobOnce([this] {
454             HandleEosInner(false);
455         });
456         return;
457     }
458     FALSE_RETURN(DropApeBuffer(filledOutputBuffer) == false);
459     UpdateAudioWriteTimeMayWait();
460     DoSyncWrite(filledOutputBuffer);
461     if (calMaxAmplitudeCbStatus_) {
462         CalcMaxAmplitude(filledOutputBuffer);
463     } else {
464         maxAmplitude_ = 0.0f;
465     }
466     lastBufferWriteSuccess_ = (plugin_->Write(filledOutputBuffer) == Status::OK);
467     int64_t nowClockTime = 0;
468     GetSyncCenterClockTime(nowClockTime);
469     lagDetector_.UpdateDrainTimeGroup(
470         { lastAnchorClockTime_, bufferDurationSinceLastAnchor_, plugin_->GetWriteDurationMs(), nowClockTime });
471     lagDetector_.CalcLag(filledOutputBuffer);
472     MEDIA_LOG_D("audio DrainOutputBuffer pts = " PUBLIC_LOG_D64, filledOutputBuffer->pts_);
473     numFramesWritten_++;
474     inputBufferQueueConsumer_->ReleaseBuffer(filledOutputBuffer);
475 }
476 
ResetSyncInfo()477 void AudioSink::ResetSyncInfo()
478 {
479     lastAnchorClockTime_ = HST_TIME_NONE;
480     forceUpdateTimeAnchorNextTime_ = true;
481 }
482 
Reset()483 void AudioSink::UnderrunDetector::Reset()
484 {
485     AutoLock lock(mutex_);
486     lastClkTime_ = HST_TIME_NONE;
487     lastLatency_ = HST_TIME_NONE;
488     lastBufferDuration_ = HST_TIME_NONE;
489 }
490 
SetEventReceiver(std::weak_ptr<Pipeline::EventReceiver> eventReceiver)491 void AudioSink::UnderrunDetector::SetEventReceiver(std::weak_ptr<Pipeline::EventReceiver> eventReceiver)
492 {
493     eventReceiver_ = eventReceiver;
494 }
495 
UpdateBufferTimeNoLock(int64_t clkTime,int64_t latency)496 void AudioSink::UnderrunDetector::UpdateBufferTimeNoLock(int64_t clkTime, int64_t latency)
497 {
498     lastClkTime_ = clkTime;
499     lastLatency_ = latency;
500 }
501 
SetLastAudioBufferDuration(int64_t durationUs)502 void AudioSink::UnderrunDetector::SetLastAudioBufferDuration(int64_t durationUs)
503 {
504     AutoLock lock(mutex_);
505     lastBufferDuration_ = durationUs;
506 }
507 
DetectAudioUnderrun(int64_t clkTime,int64_t latency)508 void AudioSink::UnderrunDetector::DetectAudioUnderrun(int64_t clkTime, int64_t latency)
509 {
510     if (lastClkTime_ == HST_TIME_NONE) {
511         AutoLock lock(mutex_);
512         UpdateBufferTimeNoLock(clkTime, latency);
513         return;
514     }
515     int64_t underrunTimeUs = 0;
516     {
517         AutoLock lock(mutex_);
518         int64_t elapsedClk = clkTime - lastClkTime_;
519         underrunTimeUs = elapsedClk - (lastLatency_ + lastBufferDuration_);
520         UpdateBufferTimeNoLock(clkTime, latency);
521     }
522     if (underrunTimeUs > 0) {
523         MEDIA_LOG_D("AudioSink maybe underrun, underrunTimeUs=" PUBLIC_LOG_D64, underrunTimeUs);
524         auto eventReceiver = eventReceiver_.lock();
525         FALSE_RETURN(eventReceiver != nullptr);
526         eventReceiver->OnDfxEvent({"AudioSink", DfxEventType::DFX_INFO_PLAYER_AUDIO_LAG, underrunTimeUs / US_TO_MS});
527     }
528 }
529 
CalcLag(std::shared_ptr<AVBuffer> buffer)530 bool AudioSink::AudioLagDetector::CalcLag(std::shared_ptr<AVBuffer> buffer)
531 {
532     (void)buffer;
533     int64_t maxMediaTime = lastDrainTimeGroup_.anchorDuration + lastDrainTimeGroup_.lastAnchorPts;
534     auto currentMediaTime = latency_ + lastDrainTimeGroup_.nowClockTime;
535     auto writeTimeMs = lastDrainTimeGroup_.writeDuration;
536     if (maxMediaTime < currentMediaTime) {
537         MEDIA_LOG_W("renderer write cost " PUBLIC_LOG_D64, writeTimeMs);
538     }
539 
540     // Calc time delays except plugin write
541     auto currentTimeMs = Plugins::GetCurrentMillisecond();
542     auto totalTimeDiff = lastDrainTimeMs_ == 0 ? 0 : currentTimeMs - lastDrainTimeMs_;
543     lastDrainTimeMs_ = currentTimeMs;
544     auto drainTimeDiff = totalTimeDiff - writeTimeMs;
545     if (drainTimeDiff > DRAIN_TIME_DIFF_WARN_MS) {
546         MEDIA_LOG_W("Audio drain cost " PUBLIC_LOG_D64, drainTimeDiff);
547     } else if (drainTimeDiff > DRAIN_TIME_DIFF_INFO_MS) {
548         MEDIA_LOG_I("Audio drain cost " PUBLIC_LOG_D64, drainTimeDiff);
549     } else {
550         MEDIA_LOG_D("Audio drain cost " PUBLIC_LOG_D64, drainTimeDiff);
551     }
552 
553     return maxMediaTime < currentMediaTime;
554 }
555 
Reset()556 void AudioSink::AudioLagDetector::Reset()
557 {
558     latency_ = 0;
559     lastDrainTimeMs_ = 0;
560     lastDrainTimeGroup_.lastAnchorPts = 0;
561     lastDrainTimeGroup_.anchorDuration = 0;
562     lastDrainTimeGroup_.writeDuration = 0;
563     lastDrainTimeGroup_.nowClockTime = 0;
564 }
565 
GetSyncCenterClockTime(int64_t & clockTime)566 bool AudioSink::GetSyncCenterClockTime(int64_t &clockTime)
567 {
568     auto syncCenter = syncCenter_.lock();
569     FALSE_RETURN_V(syncCenter != nullptr, false);
570     clockTime = syncCenter->GetClockTimeNow();
571     return true;
572 }
573 
UpdateDrainTimeGroup(AudioDrainTimeGroup group)574 void AudioSink::AudioLagDetector::UpdateDrainTimeGroup(AudioDrainTimeGroup group)
575 {
576     lastDrainTimeGroup_.lastAnchorPts = group.lastAnchorPts;
577     lastDrainTimeGroup_.anchorDuration = group.anchorDuration;
578     lastDrainTimeGroup_.writeDuration = group.writeDuration;
579     lastDrainTimeGroup_.nowClockTime = group.nowClockTime;
580 }
581 
UpdateTimeAnchorIfNeeded(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)582 bool AudioSink::UpdateTimeAnchorIfNeeded(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
583 {
584     auto syncCenter = syncCenter_.lock();
585     FALSE_RETURN_V(syncCenter != nullptr, false);
586     int64_t nowCt = syncCenter->GetClockTimeNow();
587     bool needUpdate = forceUpdateTimeAnchorNextTime_ ||
588         (lastAnchorClockTime_ == HST_TIME_NONE) ||
589         (nowCt - lastAnchorClockTime_ >= ANCHOR_UPDATE_PERIOD_US);
590     if (!needUpdate) {
591         MEDIA_LOG_D("No need to update time anchor this time.");
592         return false;
593     }
594     uint64_t latency = 0;
595     FALSE_LOG_MSG(plugin_->GetLatency(latency) == Status::OK, "failed to get latency");
596     syncCenter->UpdateTimeAnchor(nowCt, latency + fixDelay_,
597         buffer->pts_ - firstPts_, buffer->pts_, buffer->duration_, this);
598     lagDetector_.SetLatency(latency + fixDelay_);
599     MEDIA_LOG_I("AudioSink fixDelay_: " PUBLIC_LOG_D64
600         " us, latency: " PUBLIC_LOG_D64
601         " us, pts-f: " PUBLIC_LOG_D64
602         " us, pts: " PUBLIC_LOG_D64
603         " us, nowCt: " PUBLIC_LOG_D64 " us",
604         fixDelay_, latency, buffer->pts_ - firstPts_, buffer->pts_, nowCt);
605     forceUpdateTimeAnchorNextTime_ = false;
606     lastAnchorClockTime_ = nowCt;
607     return true;
608 }
609 
DoSyncWrite(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)610 int64_t AudioSink::DoSyncWrite(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
611 {
612     bool render = true; // audio sink always report time anchor and do not drop
613     auto syncCenter = syncCenter_.lock();
614     if (firstPts_ == HST_TIME_NONE) {
615         if (syncCenter && syncCenter->GetMediaStartPts() != HST_TIME_NONE) {
616             firstPts_ = syncCenter->GetMediaStartPts();
617         } else {
618             firstPts_ = buffer->pts_;
619         }
620         MEDIA_LOG_I("audio DoSyncWrite set firstPts = " PUBLIC_LOG_D64, firstPts_);
621     }
622     bool anchorUpdated = UpdateTimeAnchorIfNeeded(buffer);
623     latestBufferDuration_ = CalcBufferDuration(buffer) / speed_;
624     if (anchorUpdated) {
625         bufferDurationSinceLastAnchor_ = latestBufferDuration_;
626     } else {
627         bufferDurationSinceLastAnchor_ += latestBufferDuration_;
628     }
629     underrunDetector_.SetLastAudioBufferDuration(bufferDurationSinceLastAnchor_);
630     if (syncCenter) {
631         syncCenter->SetLastAudioBufferDuration(bufferDurationSinceLastAnchor_);
632     }
633     return render ? 0 : -1;
634 }
635 
CalcBufferDuration(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)636 int64_t AudioSink::CalcBufferDuration(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
637 {
638     FALSE_RETURN_V(buffer != nullptr && buffer->memory_ != nullptr && sampleRate_ != 0 && audioChannelCount_ != 0, 0);
639     int64_t size = static_cast<int64_t>(buffer->memory_->GetSize());
640     int32_t format = 0;
641     switch (plugin_->GetSampleFormat()) {
642         case AudioSampleFormat::SAMPLE_U8:
643             format = AUDIO_SAMPLE_8_BIT;
644             break;
645         case AudioSampleFormat::SAMPLE_S16LE:
646             format = AUDIO_SAMPLE_16_BIT;
647             break;
648         case AudioSampleFormat::SAMPLE_S24LE:
649             format = AUDIO_SAMPLE_24_BIT;
650             break;
651         case AudioSampleFormat::SAMPLE_S32LE:
652             format = AUDIO_SAMPLE_32_BIT;
653             break;
654         default:
655             break;
656     }
657     FALSE_RETURN_V(format > 0, 0);
658     return HST_MSECOND * size / format / sampleRate_ / audioChannelCount_;
659 }
660 
SetSpeed(float speed)661 Status AudioSink::SetSpeed(float speed)
662 {
663     if (plugin_ == nullptr) {
664         return Status::ERROR_NULL_POINTER;
665     }
666     if (speed <= 0) {
667         return Status::ERROR_INVALID_PARAMETER;
668     }
669     auto ret = plugin_->SetSpeed(speed);
670     if (ret == Status::OK) {
671         speed_ = speed;
672     }
673     forceUpdateTimeAnchorNextTime_ = true;
674     return ret;
675 }
676 
SetAudioEffectMode(int32_t effectMode)677 Status AudioSink::SetAudioEffectMode(int32_t effectMode)
678 {
679     MEDIA_LOG_I("AudioSink::SetAudioEffectMode entered. ");
680     if (plugin_ == nullptr) {
681         return Status::ERROR_NULL_POINTER;
682     }
683     effectMode_ = effectMode;
684     return plugin_->SetAudioEffectMode(effectMode);
685 }
686 
GetAudioEffectMode(int32_t & effectMode)687 Status AudioSink::GetAudioEffectMode(int32_t &effectMode)
688 {
689     MEDIA_LOG_I("AudioSink::GetAudioEffectMode entered.");
690     if (plugin_ == nullptr) {
691         return Status::ERROR_NULL_POINTER;
692     }
693     return plugin_->GetAudioEffectMode(effectMode);
694 }
695 
getPendingAudioPlayoutDurationUs(int64_t nowUs)696 int64_t AudioSink::getPendingAudioPlayoutDurationUs(int64_t nowUs)
697 {
698     int64_t writtenSamples = numFramesWritten_ * samplePerFrame_;
699     const int64_t numFramesPlayed = plugin_->GetPlayedOutDurationUs(nowUs);
700     int64_t pendingUs = (writtenSamples - numFramesPlayed) * HST_MSECOND/ sampleRate_;
701     MEDIA_LOG_D("pendingUs" PUBLIC_LOG_D64, pendingUs);
702     if (pendingUs < 0) {
703         pendingUs = 0;
704     }
705     return pendingUs;
706 }
707 
getDurationUsPlayedAtSampleRate(uint32_t numFrames)708 int64_t AudioSink::getDurationUsPlayedAtSampleRate(uint32_t numFrames)
709 {
710     std::shared_ptr<Meta> parameter;
711     plugin_->GetParameter(parameter);
712     int32_t sampleRate = 0;
713     if (parameter) {
714         parameter->GetData(Tag::AUDIO_SAMPLE_RATE, sampleRate);
715     }
716     if (sampleRate == 0) {
717         MEDIA_LOG_W("cannot get sampleRate");
718         return 0;
719     }
720     return (int64_t)(static_cast<int32_t>(numFrames) * HST_MSECOND / sampleRate);
721 }
722 
SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver> & receiver)723 void AudioSink::SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver>& receiver)
724 {
725     FALSE_RETURN(receiver != nullptr);
726     playerEventReceiver_ = receiver;
727     FALSE_RETURN(plugin_ != nullptr);
728     plugin_->SetEventReceiver(receiver);
729 }
730 
SetSyncCenter(std::shared_ptr<Pipeline::MediaSyncManager> syncCenter)731 void AudioSink::SetSyncCenter(std::shared_ptr<Pipeline::MediaSyncManager> syncCenter)
732 {
733     syncCenter_ = syncCenter;
734     MediaSynchronousSink::Init();
735 }
736 
ChangeTrack(std::shared_ptr<Meta> & meta,const std::shared_ptr<Pipeline::EventReceiver> & receiver)737 Status AudioSink::ChangeTrack(std::shared_ptr<Meta>& meta, const std::shared_ptr<Pipeline::EventReceiver>& receiver)
738 {
739     MEDIA_LOG_I("AudioSink::GetAudioEffectMode ChangeTrack. ");
740     std::lock_guard<std::mutex> lock(pluginMutex_);
741     Status res = Status::OK;
742 
743     if (plugin_) {
744         plugin_->Stop();
745         plugin_->Deinit();
746         plugin_ = nullptr;
747     }
748     plugin_ = CreatePlugin();
749     FALSE_RETURN_V(plugin_ != nullptr, Status::ERROR_NULL_POINTER);
750     if (meta != nullptr) {
751         meta->SetData(Tag::APP_PID, appPid_);
752         meta->SetData(Tag::APP_UID, appUid_);
753     }
754     plugin_->SetEventReceiver(receiver);
755     plugin_->SetParameter(meta);
756     plugin_->Init();
757     plugin_->Prepare();
758     plugin_->SetMuted(isMuted_);
759     meta->GetData(Tag::AUDIO_SAMPLE_RATE, sampleRate_);
760     meta->GetData(Tag::AUDIO_SAMPLE_PER_FRAME, samplePerFrame_);
761     meta->GetData(Tag::AUDIO_CHANNEL_COUNT, audioChannelCount_);
762     if (volume_ >= 0) {
763         plugin_->SetVolume(volume_);
764     }
765     if (speed_ >= 0) {
766         plugin_->SetSpeed(speed_);
767     }
768     if (effectMode_ >= 0) {
769         plugin_->SetAudioEffectMode(effectMode_);
770     }
771     if (state_ == Pipeline::FilterState::RUNNING) {
772         res = plugin_->Start();
773     }
774     forceUpdateTimeAnchorNextTime_ = true;
775     return res;
776 }
777 
SetMuted(bool isMuted)778 Status AudioSink::SetMuted(bool isMuted)
779 {
780     isMuted_ = isMuted;
781     FALSE_RETURN_V(plugin_ != nullptr, Status::ERROR_NULL_POINTER);
782     return plugin_->SetMuted(isMuted);
783 }
784 
SetSeekTime(int64_t seekTime)785 Status AudioSink::SetSeekTime(int64_t seekTime)
786 {
787     MEDIA_LOG_I("AudioSink SetSeekTime pts = " PUBLIC_LOG_D64, seekTime);
788     seekTimeUs_ = seekTime;
789     return Status::OK;
790 }
SetMaxAmplitudeCbStatus(bool status)791 int32_t AudioSink::SetMaxAmplitudeCbStatus(bool status)
792 {
793     calMaxAmplitudeCbStatus_ = status;
794     MEDIA_LOG_I("audio SetMaxAmplitudeCbStatus  = " PUBLIC_LOG_D32, calMaxAmplitudeCbStatus_);
795     return 0;
796 }
797 } // namespace MEDIA
798 } // namespace OHOS
799