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