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