• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2023 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "cache_buffer.h"
18 #include "media_log.h"
19 #include "media_errors.h"
20 #include "securec.h"
21 #include "audio_renderer_manager.h"
22 
23 namespace {
24     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "CacheBuffer"};
25     static const int32_t ERROE_GLOBAL_ID = -1;
26 }
27 
28 namespace OHOS {
29 namespace Media {
CacheBuffer(const Format & trackFormat,const int32_t & soundID,const int32_t & streamID,std::shared_ptr<ThreadPool> cacheBufferStopThreadPool)30 CacheBuffer::CacheBuffer(const Format &trackFormat, const int32_t &soundID, const int32_t &streamID,
31     std::shared_ptr<ThreadPool> cacheBufferStopThreadPool) : trackFormat_(trackFormat),
32     soundID_(soundID), streamID_(streamID), cacheBufferStopThreadPool_(cacheBufferStopThreadPool),
33     cacheDataFrameIndex_(0), havePlayedCount_(0)
34 {
35     MEDIA_LOGI("Construction CacheBuffer soundID:%{public}d, streamID:%{public}d", soundID, streamID);
36 }
37 
~CacheBuffer()38 CacheBuffer::~CacheBuffer()
39 {
40     MEDIA_LOGI("Destruction CacheBuffer soundID:%{public}d, streamID:%{public}d", soundID_, streamID_);
41     Release();
42 }
43 
SetSoundData(const std::shared_ptr<AudioBufferEntry> & cacheData,const size_t & cacheDataTotalSize)44 void CacheBuffer::SetSoundData(const std::shared_ptr<AudioBufferEntry> &cacheData, const size_t &cacheDataTotalSize)
45 {
46     fullCacheData_ = cacheData;
47     cacheDataTotalSize_ = cacheDataTotalSize;
48 }
49 
SetManager(std::weak_ptr<StreamIDManager> streamIDManager)50 void CacheBuffer::SetManager(std::weak_ptr<StreamIDManager> streamIDManager)
51 {
52     manager_ = streamIDManager;
53 }
54 
GetGlobalId(int32_t soundID)55 int32_t CacheBuffer::GetGlobalId(int32_t soundID)
56 {
57     if (auto sharedManager = manager_.lock()) {
58         return sharedManager->GetGlobalId(soundID);
59     } else {
60         return ERROE_GLOBAL_ID;
61     }
62 }
63 
DelGlobalId(int32_t globalId)64 void CacheBuffer::DelGlobalId(int32_t globalId)
65 {
66     if (auto sharedManager = manager_.lock()) {
67         sharedManager->DelGlobalId(globalId);
68     }
69 }
70 
SetGlobalId(int32_t soundID,int32_t globalId)71 void CacheBuffer::SetGlobalId(int32_t soundID, int32_t globalId)
72 {
73     if (auto sharedManager = manager_.lock()) {
74         sharedManager->SetGlobalId(soundID, globalId);
75     }
76 }
77 
IsAudioRendererCanMix(const AudioStandard::AudioRendererInfo & audioRendererInfo)78 bool CacheBuffer::IsAudioRendererCanMix(const AudioStandard::AudioRendererInfo &audioRendererInfo)
79 {
80     AudioStandard::AudioStreamType streamType = AudioStandard::AudioSystemManager::GetStreamType(
81         audioRendererInfo.contentType, audioRendererInfo.streamUsage);
82     if (streamType == AudioStandard::AudioStreamType::STREAM_MUSIC ||
83         streamType == AudioStandard::AudioStreamType::STREAM_MOVIE ||
84         streamType == AudioStandard::AudioStreamType::STREAM_SPEECH) {
85             return true;
86         }
87     return false;
88 }
89 
DealAudioRendererParams(AudioStandard::AudioRendererOptions & rendererOptions,const AudioStandard::AudioRendererInfo & audioRendererInfo)90 void CacheBuffer::DealAudioRendererParams(AudioStandard::AudioRendererOptions &rendererOptions,
91     const AudioStandard::AudioRendererInfo &audioRendererInfo)
92 {
93     int32_t sampleRate;
94     int32_t sampleFormat;
95     int32_t channelCount;
96     // Set to PCM encoding
97     rendererOptions.streamInfo.encoding = AudioStandard::AudioEncodingType::ENCODING_PCM;
98     // Get sample rate from trackFormat and set it to audiorender.
99     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE, sampleRate);
100     rendererOptions.streamInfo.samplingRate = static_cast<AudioStandard::AudioSamplingRate>(sampleRate);
101     // Get sample format from trackFormat and set it to audiorender.
102     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
103     // Align audiorender capability
104     sampleFormat_ = static_cast<AudioStandard::AudioSampleFormat>(sampleFormat);
105     rendererOptions.streamInfo.format = sampleFormat_;
106     // Get channel count from trackFormat and set it to audiorender.
107     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, channelCount);
108     audioChannel_ = static_cast<AudioStandard::AudioChannel>(channelCount);
109     rendererOptions.streamInfo.channels = audioChannel_;
110     // contentType streamUsage rendererFlags come from user.
111     if (IsAudioRendererCanMix(audioRendererInfo)) {
112         rendererOptions.strategy.concurrencyMode = AudioStandard::AudioConcurrencyMode::MIX_WITH_OTHERS;
113     }
114     rendererOptions.rendererInfo.contentType = audioRendererInfo.contentType;
115     rendererOptions.rendererInfo.streamUsage = audioRendererInfo.streamUsage;
116     rendererOptions.privacyType = AudioStandard::PRIVACY_TYPE_PUBLIC;
117     rendererFlags_ = audioRendererInfo.rendererFlags;
118     rendererOptions.rendererInfo.rendererFlags = rendererFlags_;
119     rendererOptions.rendererInfo.playerType = AudioStandard::PlayerType::PLAYER_TYPE_SOUND_POOL;
120     rendererOptions.rendererInfo.expectedPlaybackDurationBytes = static_cast<uint64_t>(cacheDataTotalSize_);
121 }
122 
CreateAudioRenderer(const AudioStandard::AudioRendererInfo & audioRendererInfo,const PlayParams & playParams)123 std::unique_ptr<AudioStandard::AudioRenderer> CacheBuffer::CreateAudioRenderer(
124     const AudioStandard::AudioRendererInfo &audioRendererInfo, const PlayParams &playParams)
125 {
126     MediaTrace trace("CacheBuffer::CreateAudioRenderer");
127     AudioStandard::AudioRendererOptions rendererOptions = {};
128     DealAudioRendererParams(rendererOptions, audioRendererInfo);
129     std::string cacheDir = "/data/storage/el2/base/temp";
130     if (playParams.cacheDir != "") {
131         cacheDir = playParams.cacheDir;
132     }
133 
134     SoundPoolXCollie soundPoolXCollie("AudioRenderer::Create time out",
135         [](void *) {
136             MEDIA_LOGI("AudioRenderer::Create time out");
137         });
138     std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer =
139         AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions);
140     soundPoolXCollie.CancelXCollieTimer();
141 
142     if (audioRenderer == nullptr) {
143         MEDIA_LOGE("create audiorenderer failed, try again.");
144         if (rendererFlags_ == AudioStandard::AUDIO_FLAG_VKB_FAST
145             || rendererFlags_ == AudioStandard::AUDIO_FLAG_VKB_NORMAL) {
146             rendererFlags_ = AudioStandard::AUDIO_FLAG_VKB_NORMAL;
147         } else {
148             rendererFlags_ = NORMAL_PLAY_RENDERER_FLAGS;
149         }
150         rendererOptions.rendererInfo.rendererFlags = rendererFlags_;
151         SoundPoolXCollie soundPoolXCollieNormal("AudioRenderer::Create normal time out",
152             [](void *) {
153                 MEDIA_LOGI("AudioRenderer::Create normal time out");
154             });
155         audioRenderer = AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions);
156         soundPoolXCollieNormal.CancelXCollieTimer();
157     }
158 
159     CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, nullptr, "Invalid audioRenderer.");
160     return audioRenderer;
161 }
162 
PrepareAudioRenderer(std::unique_ptr<AudioStandard::AudioRenderer> & audioRenderer)163 void CacheBuffer::PrepareAudioRenderer(std::unique_ptr<AudioStandard::AudioRenderer> &audioRenderer)
164 {
165     size_t targetSize = 0;
166     int32_t ret = audioRenderer->GetBufferSize(targetSize);
167     audioRenderer->SetRenderMode(AudioStandard::AudioRenderMode::RENDER_MODE_CALLBACK);
168     if (ret == 0 && targetSize != 0 && !audioRenderer->IsFastRenderer()) {
169         size_t bufferDuration = 20; // 20 -> 20ms
170         audioRenderer->SetBufferDuration(bufferDuration);
171         MEDIA_LOGI("Using buffer size:%{public}zu, duration %{public}zu", targetSize, bufferDuration);
172     }
173     int32_t retCallback = audioRenderer->SetRendererWriteCallback(shared_from_this());
174     int32_t retFirstCallback = audioRenderer->SetRendererFirstFrameWritingCallback(shared_from_this());
175     int32_t retRenderCallback = audioRenderer->SetRendererCallback(shared_from_this());
176     MEDIA_LOGI("CacheBuffer::CreateAudioRenderer retCallback:%{public}d, retFirstCallback:%{public}d,"
177         " retRenderCallback:%{public}d", retCallback, retFirstCallback, retRenderCallback);
178 }
179 
GetAvailableAudioRenderer(const AudioStandard::AudioRendererInfo & audioRendererInfo,const PlayParams & playParams)180 void CacheBuffer::GetAvailableAudioRenderer(const AudioStandard::AudioRendererInfo &audioRendererInfo,
181     const PlayParams &playParams)
182 {
183     MediaTrace trace("CacheBuffer::GetAvailableAudioRenderer");
184     MEDIA_LOGI("CacheBuffer::GetAvailableAudioRenderer start");
185     bool result = true;
186     while (result) {
187         int32_t globalId = GetGlobalId(soundID_);
188         if (globalId > 0) {
189             audioRenderer_ = AudioRendererManager::GetInstance().GetAudioRendererInstance(globalId);
190             if (audioRenderer_ != nullptr) {
191                 MEDIA_LOGI("CacheBuffer::GetAvailableAudioRenderer useOld audiorenderer,"
192                     "globalId:%{public}d, soundID:%{public}d", globalId, soundID_);
193                 break;
194             } else {
195                 DelGlobalId(globalId);
196             }
197         } else {
198             result = false;
199         }
200     }
201     if (audioRenderer_ == nullptr) {
202         MEDIA_LOGI("CacheBuffer::GetAvailableAudioRenderer CreateAudioRenderer New start");
203         audioRenderer_ = CreateAudioRenderer(audioRendererInfo, playParams);
204         if (audioRenderer_ == nullptr) {
205             AudioRendererManager::GetInstance().RemoveOldAudioRenderer();
206             MEDIA_LOGE("CacheBuffer::GetAvailableAudioRenderer CreateAudioRenderer fail, release old auidoRenderer");
207             audioRenderer_ = CreateAudioRenderer(audioRendererInfo, playParams);
208         }
209         MEDIA_LOGI("CacheBuffer::GetAvailableAudioRenderer CreateAudioRenderer New end");
210         CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "Invalid CreateAudioRenderer");
211         PrepareAudioRenderer(audioRenderer_);
212     }
213     MEDIA_LOGI("CacheBuffer::GetAvailableAudioRenderer end");
214 }
215 
PreparePlayInner(const AudioStandard::AudioRendererInfo & audioRendererInfo,const PlayParams & playParams)216 int32_t CacheBuffer::PreparePlayInner(const AudioStandard::AudioRendererInfo &audioRendererInfo,
217     const PlayParams &playParams)
218 {
219     if (audioRenderer_ != nullptr) {
220         MEDIA_LOGI("CacheBuffer::PreparePlayInner has audiorenderer available");
221         DealPlayParamsBeforePlay(playParams);
222         return MSERR_OK;
223     }
224     GetAvailableAudioRenderer(audioRendererInfo, playParams);
225     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid GetAvailableAudioRenderer");
226     DealPlayParamsBeforePlay(playParams);
227     return MSERR_OK;
228 }
229 
PreparePlay(const AudioStandard::AudioRendererInfo & audioRendererInfo,const PlayParams & playParams)230 int32_t CacheBuffer::PreparePlay(const AudioStandard::AudioRendererInfo &audioRendererInfo,
231     const PlayParams &playParams)
232 {
233     std::lock_guard lock(cacheBufferLock_);
234     playParameters_ = playParams;
235     audioRendererInfo_ = audioRendererInfo;
236     return PreparePlayInner(audioRendererInfo, playParams);
237 }
238 
DoPlay(const int32_t streamID)239 int32_t CacheBuffer::DoPlay(const int32_t streamID)
240 {
241     MediaTrace trace("CacheBuffer::DoPlay");
242     CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID, failed to DoPlay.");
243     std::lock_guard lock(cacheBufferLock_);
244     CHECK_AND_RETURN_RET_LOG(fullCacheData_ != nullptr, MSERR_INVALID_VAL, "fullCacheData_ is nullptr.");
245     if (audioRenderer_ == nullptr) {
246         MEDIA_LOGI("CacheBuffer::DoPlay audioRenderer_ is nullptr, try again");
247         PreparePlayInner(audioRendererInfo_, playParameters_);
248     }
249     MEDIA_LOGI("CacheBuffer::DoPlay start, streamID:%{public}d", streamID);
250     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
251     size_t bufferSize;
252     audioRenderer_->GetBufferSize(bufferSize);
253     MEDIA_LOGI("CacheBuffer::DoPlay, streamID_:%{public}d, bufferSize:%{public}zu, cacheDataFrameIndex_:%{public}zu,"
254         " cacheDataTotalSize_:%{public}zu", streamID_, bufferSize, cacheDataFrameIndex_, cacheDataTotalSize_);
255     audioRenderer_->SetSourceDuration(sourceDurationMs_);
256 
257     cacheDataFrameIndex_ = 0;
258     havePlayedCount_ = 0;
259     isRunning_.store(true);
260     SoundPoolXCollie soundPoolXCollie("audioRenderer::Start time out",
261         [](void *) {
262             MEDIA_LOGI("audioRenderer::Start time out");
263         });
264     if (!audioRenderer_->Start()) {
265         soundPoolXCollie.CancelXCollieTimer();
266         return HandleRendererNotStart(streamID);
267     } else {
268         soundPoolXCollie.CancelXCollieTimer();
269     }
270     MEDIA_LOGI("CacheBuffer::DoPlay success, streamID:%{public}d", streamID);
271     return MSERR_OK;
272 }
273 
HandleRendererNotStart(const int32_t streamID)274 int32_t CacheBuffer::HandleRendererNotStart(const int32_t streamID)
275 {
276     OHOS::AudioStandard::RendererState state = audioRenderer_->GetStatus();
277     if (state == OHOS::AudioStandard::RendererState::RENDERER_RUNNING) {
278         MEDIA_LOGI("CacheBuffer::HandleRendererNotStart audioRenderer has started,"
279             " streamID:%{public}d", streamID);
280         isRunning_.store(true);
281         if (callback_ != nullptr) {
282             MEDIA_LOGI("CacheBuffer::HandleRendererNotStart callback_ OnPlayFinished,"
283                 "streamID:%{public}d", streamID);
284             callback_->OnPlayFinished(streamID_);
285         }
286         isNeedFadeIn_ = true;
287         return MSERR_OK;
288     } else {
289         MEDIA_LOGE("CacheBuffer::HandleRendererNotStart audioRenderer start failed,"
290             "streamID:%{public}d", streamID);
291         isRunning_.store(false);
292         if (callback_ != nullptr) {
293             MEDIA_LOGI("CacheBuffer::HandleRendererNotStart doPlay failed, call callback,"
294                 "streamID:%{public}d", streamID);
295             callback_->OnError(MSERR_INVALID_VAL);
296             SoundPoolUtils::ErrorInfo errorInfo{MSERR_INVALID_VAL, soundID_,
297                 streamID_, ERROR_TYPE::PLAY_ERROR, callback_};
298             SoundPoolUtils::SendErrorInfo(errorInfo);
299         }
300         if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnError(MSERR_INVALID_VAL);
301         return MSERR_INVALID_VAL;
302     }
303 }
304 
DealPlayParamsBeforePlay(const PlayParams & playParams)305 void CacheBuffer::DealPlayParamsBeforePlay(const PlayParams &playParams)
306 {
307     audioRenderer_->SetOffloadAllowed(false);
308     loop_ = playParams.loop;
309     audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(playParams.rate));
310     audioRenderer_->SetVolume(playParams.leftVolume);
311     priority_ = playParams.priority;
312     audioRenderer_->SetParallelPlayFlag(playParams.parallelPlayFlag);
313     audioRenderer_->SetAudioHapticsSyncId(playParams.audioHapticsSyncId);
314     MEDIA_LOGI("CacheBuffer::DealPlayParamsBeforePlay end");
315 }
316 
CheckAndAlignRendererRate(const int32_t rate)317 AudioStandard::AudioRendererRate CacheBuffer::CheckAndAlignRendererRate(const int32_t rate)
318 {
319     AudioStandard::AudioRendererRate renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
320     switch (rate) {
321         case AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL:
322             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
323             break;
324         case AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE:
325             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE;
326             break;
327         case AudioStandard::AudioRendererRate::RENDER_RATE_HALF:
328             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_HALF;
329             break;
330         default:
331             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
332             break;
333     }
334     return renderRate;
335 }
336 
OnWriteData(size_t length)337 void CacheBuffer::OnWriteData(size_t length)
338 {
339     if (audioRenderer_ == nullptr) {
340         MEDIA_LOGE("audioRenderer is nullptr.");
341         return;
342     }
343     if (!isRunning_.load()) {
344         MEDIA_LOGE("audioRenderer is stop.");
345         return;
346     }
347     CHECK_AND_RETURN_LOG(isReadyToStopAudioRenderer_.load() == false,
348         "CacheBuffer::OnWriteData is ready To stop AudioRenderer, streamID:%{public}d", streamID_);
349     std::lock_guard lock(cacheBufferLock_);
350     CHECK_AND_RETURN_LOG(fullCacheData_ != nullptr, "fullCacheData_ is nullptr");
351     if (cacheDataFrameIndex_ >= static_cast<size_t>(fullCacheData_->size)) {
352         if (loop_ >= 0 && havePlayedCount_ >= loop_) {
353             MEDIA_LOGI("CacheBuffer stream write finish, cacheDataFrameIndex_:%{public}zu,"
354                 " havePlayedCount_:%{public}d, loop:%{public}d, streamID_:%{public}d, length: %{public}zu",
355                 cacheDataFrameIndex_, havePlayedCount_, loop_, streamID_, length);
356             int32_t streamIDStop = streamID_;
357             ThreadPool::Task cacheBufferStopTask = [this, streamIDStop] { this->Stop(streamIDStop); };
358             if (auto ptr = cacheBufferStopThreadPool_.lock()) {
359                 ptr->AddTask(cacheBufferStopTask);
360                 isReadyToStopAudioRenderer_.store(true);
361             }
362             return;
363         }
364         cacheDataFrameIndex_ = 0;
365         havePlayedCount_++;
366     }
367     DealWriteData(length);
368 }
369 
DealWriteData(size_t length)370 void CacheBuffer::DealWriteData(size_t length)
371 {
372     CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "DealWriteData audioRenderer_ is nullptr");
373     AudioStandard::BufferDesc bufDesc;
374     audioRenderer_->GetBufferDesc(bufDesc);
375     if (bufDesc.buffer != nullptr && fullCacheData_ != nullptr && fullCacheData_->buffer != nullptr) {
376         if (static_cast<size_t>(fullCacheData_->size) - cacheDataFrameIndex_ >= length) {
377             int32_t ret = memcpy_s(bufDesc.buffer, length,
378                 fullCacheData_->buffer + cacheDataFrameIndex_, length);
379             CHECK_AND_RETURN_LOG(ret == MSERR_OK, "memcpy failed total length.");
380             bufDesc.bufLength = length;
381             bufDesc.dataLength = length;
382             cacheDataFrameIndex_ += length;
383         } else {
384             size_t copyLength = static_cast<size_t>(fullCacheData_->size) - cacheDataFrameIndex_;
385             int32_t ret = AudioStandard::AudioRenderer::MuteAudioBuffer(bufDesc.buffer, 0, length, sampleFormat_);
386             CHECK_AND_RETURN_LOG(ret == AudioStandard::SUCCESS, "fill mute buffer failed.");
387             ret = memcpy_s(bufDesc.buffer, length, fullCacheData_->buffer + cacheDataFrameIndex_,
388                 copyLength);
389             CHECK_AND_RETURN_LOG(ret == MSERR_OK, "memcpy failed not enough length.");
390             bufDesc.bufLength = length;
391             bufDesc.dataLength = length;
392             cacheDataFrameIndex_ += copyLength;
393         }
394         FadeInAudioBuffer(bufDesc);
395         audioRenderer_->Enqueue(bufDesc);
396         if (cacheDataFrameIndex_ >= static_cast<size_t>(fullCacheData_->size) &&
397             (loop_ < 0 || havePlayedCount_ < loop_)) {
398             MEDIA_LOGI("DealWriteData ResetFirstFrameState when looping");
399             audioRenderer_->ResetFirstFrameState();
400         }
401     } else if (fullCacheData_ != nullptr) {
402         MEDIA_LOGE("OnWriteData, cacheDataFrameIndex_: %{public}zu, length: %{public}zu,"
403             " bufDesc.buffer:%{public}d, fullCacheData_:1, fullCacheData_->buffer:%{public}d,"
404             " streamID_:%{public}d",
405             cacheDataFrameIndex_, length, bufDesc.buffer != nullptr,
406             fullCacheData_->buffer != nullptr, streamID_);
407     } else {
408         MEDIA_LOGE("OnWriteData, cacheDataFrameIndex_: %{public}zu, length: %{public}zu,"
409             " bufDesc.buffer:%{public}d, fullCacheData_:0, streamID_:%{public}d",
410             cacheDataFrameIndex_, length, bufDesc.buffer != nullptr, streamID_);
411     }
412 }
413 
OnFirstFrameWriting(uint64_t latency)414 void CacheBuffer::OnFirstFrameWriting(uint64_t latency)
415 {
416     MEDIA_LOGI("CacheBuffer::OnFirstFrameWriting, streamID_:%{public}d", streamID_);
417     CHECK_AND_RETURN_LOG(frameWriteCallback_ != nullptr, "frameWriteCallback is null.");
418     frameWriteCallback_->OnFirstAudioFrameWritingCallback(latency);
419 }
420 
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)421 void CacheBuffer::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
422 {
423     MEDIA_LOGI("CacheBuffer::OnInterrupt, streamID_:%{public}d, eventType:%{public}d, forceType:%{public}d,"
424         "hintType:%{public}d", streamID_, interruptEvent.eventType, interruptEvent.forceType,
425         interruptEvent.hintType);
426     if (interruptEvent.hintType == AudioStandard::InterruptHint::INTERRUPT_HINT_PAUSE ||
427         interruptEvent.hintType == AudioStandard::InterruptHint::INTERRUPT_HINT_STOP) {
428         MEDIA_LOGI("CacheBuffer::OnInterrupt, interrupt cacheBuffer, streamID_:%{public}d", streamID_);
429         int32_t streamIDInterrupt = streamID_;
430         ThreadPool::Task cacheBufferInterruptTask = [this, streamIDInterrupt] { this->Stop(streamIDInterrupt); };
431         if (auto ptr = cacheBufferStopThreadPool_.lock()) {
432             ptr->AddTask(cacheBufferInterruptTask);
433         }
434     }
435 }
436 
OnStateChange(const AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)437 void CacheBuffer::OnStateChange(const AudioStandard::RendererState state,
438     const AudioStandard::StateChangeCmdType cmdType)
439 {
440     MEDIA_LOGI("CacheBuffer::OnStateChange, state:%{public}d", state);
441 }
442 
Stop(const int32_t streamID)443 int32_t CacheBuffer::Stop(const int32_t streamID)
444 {
445     MediaTrace trace("CacheBuffer::Stop");
446     MEDIA_LOGI("CacheBuffer::Stop streamID:%{public}d", streamID_);
447     std::lock_guard lock(cacheBufferLock_);
448     CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID_.");
449     if (audioRenderer_ != nullptr && isRunning_.load()) {
450         isRunning_.store(false);
451         SoundPoolXCollie soundPoolXCollie("audioRenderer::Pause or Stop time out",
452             [](void *) {
453                 MEDIA_LOGI("audioRenderer::Pause or Stop time out");
454             });
455         if (audioRenderer_->IsFastRenderer()) {
456             MEDIA_LOGI("audioRenderer fast renderer pause.");
457             audioRenderer_->Pause();
458             audioRenderer_->Flush();
459         } else {
460             MEDIA_LOGI("audioRenderer normal stop.");
461             audioRenderer_->Stop();
462         }
463         soundPoolXCollie.CancelXCollieTimer();
464         cacheDataFrameIndex_ = 0;
465         havePlayedCount_ = 0;
466         if (callback_ != nullptr) {
467             MEDIA_LOGI("cachebuffer callback_ OnPlayFinished.");
468             callback_->OnPlayFinished(streamID_);
469         }
470         int32_t globalId = AudioRendererManager::GetInstance().GetGlobalId();
471         AudioRendererManager::GetInstance().SetAudioRendererInstance(globalId, std::move(audioRenderer_));
472         SetGlobalId(soundID_, globalId);
473         if (cacheBufferCallback_ != nullptr) {
474             MEDIA_LOGI("cachebuffer cacheBufferCallback_ OnPlayFinished.");
475             cacheBufferCallback_->OnPlayFinished(streamID_);
476         }
477     } else {
478         MEDIA_LOGI("CacheBuffer::Stop isRunning_:%{public}d", isRunning_.load());
479     }
480     isReadyToStopAudioRenderer_.store(false);
481     return MSERR_OK;
482 }
483 
SetVolume(const int32_t streamID,const float leftVolume,const float rightVolume)484 int32_t CacheBuffer::SetVolume(const int32_t streamID, const float leftVolume, const float rightVolume)
485 {
486     std::lock_guard lock(cacheBufferLock_);
487     int32_t ret = MSERR_OK;
488     if (streamID == streamID_) {
489         if (audioRenderer_ != nullptr) {
490             MEDIA_LOGI("CacheBuffer::SetVolume start streamID:%{public}d", streamID_);
491             // audio cannot support left & right volume, all use left volume.
492             (void) rightVolume;
493             ret = audioRenderer_->SetVolume(leftVolume);
494         }
495     }
496     return ret;
497 }
498 
SetRate(const int32_t streamID,const AudioStandard::AudioRendererRate renderRate)499 int32_t CacheBuffer::SetRate(const int32_t streamID, const AudioStandard::AudioRendererRate renderRate)
500 {
501     std::lock_guard lock(cacheBufferLock_);
502     int32_t ret = MSERR_OK;
503     if (streamID == streamID_) {
504         if (audioRenderer_ != nullptr) {
505             MEDIA_LOGI("CacheBuffer::SetRate start streamID:%{public}d", streamID_);
506             ret = audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(renderRate));
507         }
508     }
509     return ret;
510 }
511 
SetPriority(const int32_t streamID,const int32_t priority)512 int32_t CacheBuffer::SetPriority(const int32_t streamID, const int32_t priority)
513 {
514     std::lock_guard lock(cacheBufferLock_);
515     if (streamID == streamID_) {
516         priority_ = priority;
517     }
518     return MSERR_OK;
519 }
520 
SetLoop(const int32_t streamID,const int32_t loop)521 int32_t CacheBuffer::SetLoop(const int32_t streamID, const int32_t loop)
522 {
523     std::lock_guard lock(cacheBufferLock_);
524     if (streamID == streamID_) {
525         loop_ = loop;
526         havePlayedCount_ = 0;
527     }
528     return MSERR_OK;
529 }
530 
SetParallelPlayFlag(const int32_t streamID,const bool parallelPlayFlag)531 int32_t CacheBuffer::SetParallelPlayFlag(const int32_t streamID, const bool parallelPlayFlag)
532 {
533     std::lock_guard lock(cacheBufferLock_);
534     if (streamID == streamID_) {
535         if (audioRenderer_ != nullptr) {
536             MEDIA_LOGI("CacheBuffer parallelPlayFlag:%{public}d.", parallelPlayFlag);
537             audioRenderer_->SetParallelPlayFlag(parallelPlayFlag);
538         }
539     }
540     return MSERR_OK;
541 }
542 
Release()543 int32_t CacheBuffer::Release()
544 {
545     MediaTrace trace("CacheBuffer::Release");
546     // Define a temporary variable.Let audioRenderer_ to audioRenderer can protect audioRenderer_ concurrently
547     // modified.So will not cause null pointers.
548     std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer;
549     {
550         std::lock_guard lock(cacheBufferLock_);
551         audioRenderer = std::move(audioRenderer_);
552         audioRenderer_ = nullptr;
553         isRunning_.store(false);
554     }
555 
556     MEDIA_LOGI("CacheBuffer::Release start, streamID:%{public}d", streamID_);
557     // Use audioRenderer to release and don't lock, so it will not cause dead lock. if here locked, audioRenderer
558     // will wait callback thread stop, and the callback thread can't get the lock, it will cause dead lock
559     if (audioRenderer != nullptr) {
560         SoundPoolXCollie soundPoolXCollie("Release audioRenderer::Stop time out",
561             [](void *) {
562                 MEDIA_LOGI("Release audioRenderer::Stop time out");
563             });
564         audioRenderer->Stop();
565         soundPoolXCollie.CancelXCollieTimer();
566         SoundPoolXCollie soundPoolXCollieRelease("Release audioRenderer::Release time out",
567         [](void *) {
568             MEDIA_LOGI("Release audioRenderer::Release time out");
569         });
570         audioRenderer->Release();
571         soundPoolXCollieRelease.CancelXCollieTimer();
572         audioRenderer = nullptr;
573     }
574 
575     std::lock_guard lock(cacheBufferLock_);
576     if (!cacheData_.empty()) cacheData_.clear();
577     if (fullCacheData_ != nullptr) fullCacheData_.reset();
578     if (callback_ != nullptr) callback_.reset();
579     if (cacheBufferCallback_ != nullptr) cacheBufferCallback_.reset();
580     if (frameWriteCallback_ != nullptr) frameWriteCallback_.reset();
581     MEDIA_LOGI("CacheBuffer::Release end, streamID:%{public}d", streamID_);
582     return MSERR_OK;
583 }
584 
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)585 int32_t CacheBuffer::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
586 {
587     callback_ = callback;
588     return MSERR_OK;
589 }
590 
SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> & callback)591 int32_t CacheBuffer::SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
592 {
593     cacheBufferCallback_ = callback;
594     return MSERR_OK;
595 }
596 
SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & callback)597 int32_t CacheBuffer::SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> &callback)
598 {
599     frameWriteCallback_ = callback;
600     return MSERR_OK;
601 }
602 
SetSourceDuration(int64_t durationMs)603 void CacheBuffer::SetSourceDuration(int64_t durationMs)
604 {
605     sourceDurationMs_ = durationMs;
606 }
607 
FadeInAudioBuffer(const AudioStandard::BufferDesc & bufDesc)608 void CacheBuffer::FadeInAudioBuffer(const AudioStandard::BufferDesc &bufDesc)
609 {
610     if (isNeedFadeIn_) {
611         isNeedFadeIn_ = false;
612         MEDIA_LOGI("CacheBuffer::FadeInAudioBuffer, streamID:%{public}d", streamID_);
613         int32_t ret = AudioStandard::AudioRenderer::FadeInAudioBuffer(bufDesc, sampleFormat_, audioChannel_);
614         if (ret != AudioStandard::SUCCESS) {
615             MEDIA_LOGW("CacheBuffer::FadeInAudioBuffer failed ret: %{public}d, streamID:%{public}d", ret, streamID_);
616         }
617     }
618 }
619 } // namespace Media
620 } // namespace OHOS
621