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