• 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 
22 namespace {
23     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "CacheBuffer"};
24 }
25 
26 namespace OHOS {
27 namespace Media {
CacheBuffer(const Format & trackFormat,const std::deque<std::shared_ptr<AudioBufferEntry>> & cacheData,const size_t & cacheDataTotalSize,const int32_t & soundID,const int32_t & streamID,std::shared_ptr<ThreadPool> cacheBufferStopThreadPool)28 CacheBuffer::CacheBuffer(const Format &trackFormat,
29     const std::deque<std::shared_ptr<AudioBufferEntry>> &cacheData,
30     const size_t &cacheDataTotalSize, const int32_t &soundID, const int32_t &streamID,
31     std::shared_ptr<ThreadPool> cacheBufferStopThreadPool) : trackFormat_(trackFormat),
32     cacheData_(cacheData), cacheDataTotalSize_(cacheDataTotalSize), soundID_(soundID), streamID_(streamID),
33     cacheBufferStopThreadPool_(cacheBufferStopThreadPool), cacheDataFrameIndex_(0), havePlayedCount_(0)
34 
35 {
36     MEDIA_LOGI("Construction CacheBuffer soundID:%{public}d, streamID:%{public}d", soundID, streamID);
37 }
38 
~CacheBuffer()39 CacheBuffer::~CacheBuffer()
40 {
41     MEDIA_LOGI("Destruction CacheBuffer soundID:%{public}d, streamID:%{public}d", soundID_, streamID_);
42     Release();
43 }
44 
IsAudioRendererCanMix(const AudioStandard::AudioRendererInfo & audioRendererInfo)45 bool CacheBuffer::IsAudioRendererCanMix(const AudioStandard::AudioRendererInfo &audioRendererInfo)
46 {
47     AudioStandard::AudioStreamType streamType = AudioStandard::AudioSystemManager::GetStreamType(
48         audioRendererInfo.contentType, audioRendererInfo.streamUsage);
49     if (streamType == AudioStandard::AudioStreamType::STREAM_MUSIC ||
50         streamType == AudioStandard::AudioStreamType::STREAM_MOVIE ||
51         streamType == AudioStandard::AudioStreamType::STREAM_SPEECH) {
52             return true;
53         }
54     return false;
55 }
56 
DealAudioRendererParams(AudioStandard::AudioRendererOptions & rendererOptions,const AudioStandard::AudioRendererInfo & audioRendererInfo)57 void CacheBuffer::DealAudioRendererParams(AudioStandard::AudioRendererOptions &rendererOptions,
58     const AudioStandard::AudioRendererInfo &audioRendererInfo)
59 {
60     int32_t sampleRate;
61     int32_t sampleFormat;
62     int32_t channelCount;
63     // Set to PCM encoding
64     rendererOptions.streamInfo.encoding = AudioStandard::AudioEncodingType::ENCODING_PCM;
65     // Get sample rate from trackFormat and set it to audiorender.
66     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE, sampleRate);
67     rendererOptions.streamInfo.samplingRate = static_cast<AudioStandard::AudioSamplingRate>(sampleRate);
68     // Get sample format from trackFormat and set it to audiorender.
69     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
70     // Align audiorender capability
71     sampleFormat_ = static_cast<AudioStandard::AudioSampleFormat>(sampleFormat);
72     rendererOptions.streamInfo.format = sampleFormat_;
73     // Get channel count from trackFormat and set it to audiorender.
74     trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, channelCount);
75     rendererOptions.streamInfo.channels = static_cast<AudioStandard::AudioChannel>(channelCount);
76     // contentType streamUsage rendererFlags come from user.
77     if (IsAudioRendererCanMix(audioRendererInfo)) {
78         rendererOptions.strategy.concurrencyMode = AudioStandard::AudioConcurrencyMode::MIX_WITH_OTHERS;
79     }
80     rendererOptions.rendererInfo.contentType = audioRendererInfo.contentType;
81     rendererOptions.rendererInfo.streamUsage = audioRendererInfo.streamUsage;
82     rendererOptions.privacyType = AudioStandard::PRIVACY_TYPE_PUBLIC;
83     rendererFlags_ = audioRendererInfo.rendererFlags;
84     rendererOptions.rendererInfo.rendererFlags = rendererFlags_;
85     rendererOptions.rendererInfo.playerType = AudioStandard::PlayerType::PLAYER_TYPE_SOUND_POOL;
86     rendererOptions.rendererInfo.expectedPlaybackDurationBytes = static_cast<uint64_t>(cacheDataTotalSize_);
87 }
88 
CreateAudioRenderer(const int32_t streamID,const AudioStandard::AudioRendererInfo audioRendererInfo,const PlayParams playParams)89 std::unique_ptr<AudioStandard::AudioRenderer> CacheBuffer::CreateAudioRenderer(const int32_t streamID,
90     const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams)
91 {
92     MediaTrace trace("CacheBuffer::CreateAudioRenderer");
93     CHECK_AND_RETURN_RET_LOG(streamID == streamID_, nullptr,
94         "Invalid streamID, failed to create normal audioRenderer.");
95     AudioStandard::AudioRendererOptions rendererOptions = {};
96     DealAudioRendererParams(rendererOptions, audioRendererInfo);
97     std::string cacheDir = "/data/storage/el2/base/temp";
98     if (playParams.cacheDir != "") {
99         cacheDir = playParams.cacheDir;
100     }
101 
102     SoundPoolXCollie soundPoolXCollie("AudioRenderer::Create time out",
103         [](void *) {
104             MEDIA_LOGI("AudioRenderer::Create time out");
105         });
106     std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer =
107         AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions);
108     soundPoolXCollie.CancelXCollieTimer();
109 
110     if (audioRenderer == nullptr) {
111         MEDIA_LOGE("create audiorenderer failed, try again.");
112         rendererFlags_ = NORMAL_PLAY_RENDERER_FLAGS;
113         rendererOptions.rendererInfo.rendererFlags = rendererFlags_;
114         SoundPoolXCollie soundPoolXCollieNormal("AudioRenderer::Create normal time out",
115             [](void *) {
116                 MEDIA_LOGI("AudioRenderer::Create normal time out");
117             });
118         audioRenderer = AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions);
119         soundPoolXCollieNormal.CancelXCollieTimer();
120     }
121 
122     CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, nullptr, "Invalid audioRenderer.");
123     PrepareAudioRenderer(audioRenderer);
124     return audioRenderer;
125 }
126 
PrepareAudioRenderer(std::unique_ptr<AudioStandard::AudioRenderer> & audioRenderer)127 void CacheBuffer::PrepareAudioRenderer(std::unique_ptr<AudioStandard::AudioRenderer> &audioRenderer)
128 {
129     size_t targetSize = 0;
130     int32_t ret = audioRenderer->GetBufferSize(targetSize);
131     audioRenderer->SetRenderMode(AudioStandard::AudioRenderMode::RENDER_MODE_CALLBACK);
132     if (ret == 0 && targetSize != 0 && !audioRenderer->IsFastRenderer()) {
133         size_t bufferDuration = 20; // 20 -> 20ms
134         audioRenderer->SetBufferDuration(bufferDuration);
135         MEDIA_LOGI("Using buffer size:%{public}zu, duration %{public}zu", targetSize, bufferDuration);
136     }
137     int32_t retCallback = audioRenderer->SetRendererWriteCallback(shared_from_this());
138     int32_t retFirstCallback = audioRenderer->SetRendererFirstFrameWritingCallback(shared_from_this());
139     int32_t retRenderCallback = audioRenderer->SetRendererCallback(shared_from_this());
140     MEDIA_LOGI("CacheBuffer::CreateAudioRenderer retCallback:%{public}d, retFirstCallback:%{public}d,"
141         " retRenderCallback:%{public}d", retCallback, retFirstCallback, retRenderCallback);
142 }
143 
PreparePlay(const int32_t streamID,const AudioStandard::AudioRendererInfo audioRendererInfo,const PlayParams playParams)144 int32_t CacheBuffer::PreparePlay(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo,
145     const PlayParams playParams)
146 {
147     // create audioRenderer
148     if (audioRenderer_ == nullptr) {
149         MEDIA_LOGI("CacheBuffer::PreparePlay CreateAudioRenderer start streamID:%{public}d", streamID);
150         audioRenderer_ = CreateAudioRenderer(streamID, audioRendererInfo, playParams);
151         MEDIA_LOGI("CacheBuffer::PreparePlay CreateAudioRenderer end streamID:%{public}d", streamID);
152         CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid CreateAudioRenderer");
153         int32_t ret = ReCombineCacheData();
154         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "Invalid ReCombineCacheData");
155     } else {
156         MEDIA_LOGI("CacheBuffer::PreparePlay audioRenderer inited, streamID:%{public}d", streamID);
157     }
158     // deal play params
159     int32_t result = DealPlayParamsBeforePlay(streamID, playParams);
160     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, MSERR_INVALID_VAL, "Invalid DealPlayParamsBeforePlay");
161     return MSERR_OK;
162 }
163 
DoPlay(const int32_t streamID)164 int32_t CacheBuffer::DoPlay(const int32_t streamID)
165 {
166     MediaTrace trace("CacheBuffer::DoPlay");
167     CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID, failed to DoPlay.");
168     std::lock_guard lock(cacheBufferLock_);
169     CHECK_AND_RETURN_RET_LOG(fullCacheData_ != nullptr, MSERR_INVALID_VAL, "fullCacheData_ is nullptr.");
170     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
171     size_t bufferSize;
172     audioRenderer_->GetBufferSize(bufferSize);
173     MEDIA_LOGI("CacheBuffer::DoPlay, streamID_:%{public}d, bufferSize:%{public}zu, cacheDataFrameIndex_:%{public}zu",
174         streamID_, bufferSize, cacheDataFrameIndex_);
175     cacheDataFrameIndex_ = 0;
176     havePlayedCount_ = 0;
177     isRunning_.store(true);
178     SoundPoolXCollie soundPoolXCollie("audioRenderer::Start time out",
179         [](void *) {
180             MEDIA_LOGI("audioRenderer::Start time out");
181         });
182     if (!audioRenderer_->Start()) {
183         soundPoolXCollie.CancelXCollieTimer();
184         OHOS::AudioStandard::RendererState state = audioRenderer_->GetStatus();
185         if (state == OHOS::AudioStandard::RendererState::RENDERER_RUNNING) {
186             MEDIA_LOGI("CacheBuffer::DoPlay audioRenderer has started, streamID:%{public}d", streamID);
187             isRunning_.store(true);
188             if (callback_ != nullptr) {
189                 MEDIA_LOGI("CacheBuffer::DoPlay callback_ OnPlayFinished, streamID:%{public}d", streamID);
190                 callback_->OnPlayFinished(streamID_);
191             }
192             return MSERR_OK;
193         } else {
194             MEDIA_LOGE("CacheBuffer::DoPlay audioRenderer start failed, streamID:%{public}d", streamID);
195             isRunning_.store(false);
196             if (callback_ != nullptr) {
197                 MEDIA_LOGI("CacheBuffer::DoPlay failed, call callback, streamID:%{public}d", streamID);
198                 callback_->OnError(MSERR_INVALID_VAL);
199             }
200             if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnError(MSERR_INVALID_VAL);
201             return MSERR_INVALID_VAL;
202         }
203     } else {
204         soundPoolXCollie.CancelXCollieTimer();
205     }
206     MEDIA_LOGI("CacheBuffer::DoPlay success, streamID:%{public}d", streamID);
207     return MSERR_OK;
208 }
209 
ReCombineCacheData()210 int32_t CacheBuffer::ReCombineCacheData()
211 {
212     std::lock_guard lock(cacheBufferLock_);
213     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
214     CHECK_AND_RETURN_RET_LOG(!cacheData_.empty(), MSERR_INVALID_VAL, "empty cache data.");
215 
216     uint8_t *fullBuffer = new(std::nothrow) uint8_t[cacheDataTotalSize_];
217     CHECK_AND_RETURN_RET_LOG(fullBuffer != nullptr, MSERR_INVALID_VAL, "Invalid fullBuffer");
218     int32_t copyIndex = 0;
219     int32_t remainBufferSize = static_cast<int32_t>(cacheDataTotalSize_);
220     MEDIA_LOGI("ReCombine start copyIndex:%{public}d, remainSize:%{public}d", copyIndex, remainBufferSize);
221     for (std::shared_ptr<AudioBufferEntry> bufferEntry : cacheData_) {
222         if (bufferEntry != nullptr && bufferEntry->size > 0 && bufferEntry->buffer != nullptr) {
223             if (remainBufferSize < bufferEntry->size) {
224                 delete[] fullBuffer;
225                 MEDIA_LOGE("ReCombine not enough remainBufferSize:%{public}d, bufferEntry->size:%{public}d",
226                     remainBufferSize, bufferEntry->size);
227                 return MSERR_INVALID_VAL;
228             }
229             int32_t ret = memcpy_s(fullBuffer + copyIndex, remainBufferSize,
230                 bufferEntry->buffer, bufferEntry->size);
231             if (ret != MSERR_OK) {
232                 delete[] fullBuffer;
233                 MEDIA_LOGE("ReCombine memcpy failed");
234                 return MSERR_INVALID_VAL;
235             }
236             copyIndex += bufferEntry->size;
237             remainBufferSize -= bufferEntry->size;
238         } else {
239             MEDIA_LOGE("ReCombineCacheData, bufferEntry size:%{public}d, buffer:%{public}d",
240                 bufferEntry->size, bufferEntry->buffer != nullptr);
241         }
242     }
243     MEDIA_LOGI("ReCombine finish copyIndex:%{public}d, remainSize:%{public}d", copyIndex, remainBufferSize);
244 
245     fullCacheData_ = std::make_shared<AudioBufferEntry>(fullBuffer, cacheDataTotalSize_);
246 
247     if (!cacheData_.empty()) {
248         cacheData_.clear();
249     }
250 
251     return MSERR_OK;
252 }
253 
DealPlayParamsBeforePlay(const int32_t streamID,const PlayParams playParams)254 int32_t CacheBuffer::DealPlayParamsBeforePlay(const int32_t streamID, const PlayParams playParams)
255 {
256     std::lock_guard lock(cacheBufferLock_);
257     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
258     audioRenderer_->SetOffloadAllowed(false);
259     loop_ = playParams.loop;
260     audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(playParams.rate));
261     audioRenderer_->SetVolume(playParams.leftVolume);
262     priority_ = playParams.priority;
263     audioRenderer_->SetParallelPlayFlag(playParams.parallelPlayFlag);
264     return MSERR_OK;
265 }
266 
CheckAndAlignRendererRate(const int32_t rate)267 AudioStandard::AudioRendererRate CacheBuffer::CheckAndAlignRendererRate(const int32_t rate)
268 {
269     AudioStandard::AudioRendererRate renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
270     switch (rate) {
271         case AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL:
272             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
273             break;
274         case AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE:
275             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE;
276             break;
277         case AudioStandard::AudioRendererRate::RENDER_RATE_HALF:
278             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_HALF;
279             break;
280         default:
281             renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
282             break;
283     }
284     return renderRate;
285 }
286 
OnWriteData(size_t length)287 void CacheBuffer::OnWriteData(size_t length)
288 {
289     if (audioRenderer_ == nullptr) {
290         MEDIA_LOGE("audioRenderer is nullptr.");
291         return;
292     }
293     if (!isRunning_.load()) {
294         MEDIA_LOGE("audioRenderer is stop.");
295         return;
296     }
297     if (cacheDataFrameIndex_ >= static_cast<size_t>(fullCacheData_->size)) {
298         cacheBufferLock_.lock();
299         if (loop_ >= 0 && havePlayedCount_ >= loop_) {
300             MEDIA_LOGI("CacheBuffer stream write finish, cacheDataFrameIndex_:%{public}zu,"
301                 " havePlayedCount_:%{public}d, loop:%{public}d, streamID_:%{public}d, length: %{public}zu",
302                 cacheDataFrameIndex_, havePlayedCount_, loop_, streamID_, length);
303             cacheBufferLock_.unlock();
304             int32_t streamIDStop = streamID_;
305             ThreadPool::Task cacheBufferStopTask = [this, streamIDStop] { this->Stop(streamIDStop); };
306             if (auto ptr = cacheBufferStopThreadPool_.lock()) {
307                 ptr->AddTask(cacheBufferStopTask);
308             }
309             return;
310         }
311         cacheDataFrameIndex_ = 0;
312         havePlayedCount_++;
313         cacheBufferLock_.unlock();
314     }
315     DealWriteData(length);
316 }
317 
DealWriteData(size_t length)318 void CacheBuffer::DealWriteData(size_t length)
319 {
320     std::lock_guard lock(cacheBufferLock_);
321     CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "DealWriteData audioRenderer_ is nullptr");
322     AudioStandard::BufferDesc bufDesc;
323     audioRenderer_->GetBufferDesc(bufDesc);
324     if (bufDesc.buffer != nullptr && fullCacheData_ != nullptr && fullCacheData_->buffer != nullptr) {
325         if (static_cast<size_t>(fullCacheData_->size) - cacheDataFrameIndex_ >= length) {
326             int32_t ret = memcpy_s(bufDesc.buffer, length,
327                 fullCacheData_->buffer + cacheDataFrameIndex_, length);
328             CHECK_AND_RETURN_LOG(ret == MSERR_OK, "memcpy failed total length.");
329             bufDesc.bufLength = length;
330             bufDesc.dataLength = length;
331             cacheDataFrameIndex_ += length;
332         } else {
333             size_t copyLength = static_cast<size_t>(fullCacheData_->size) - cacheDataFrameIndex_;
334             int32_t ret = AudioStandard::AudioRenderer::MuteAudioBuffer(bufDesc.buffer, 0, length, sampleFormat_);
335             CHECK_AND_RETURN_LOG(ret == AudioStandard::SUCCESS, "fill mute buffer failed.");
336             ret = memcpy_s(bufDesc.buffer, length, fullCacheData_->buffer + cacheDataFrameIndex_,
337                 copyLength);
338             CHECK_AND_RETURN_LOG(ret == MSERR_OK, "memcpy failed not enough length.");
339             bufDesc.bufLength = length;
340             bufDesc.dataLength = length;
341             cacheDataFrameIndex_ += copyLength;
342         }
343         audioRenderer_->Enqueue(bufDesc);
344     } else {
345         MEDIA_LOGE("OnWriteData, cacheDataFrameIndex_: %{public}zu, length: %{public}zu,"
346             " bufDesc.buffer:%{public}d, fullCacheData_:%{public}d, fullCacheData_->buffer:%{public}d,"
347             " streamID_:%{public}d",
348             cacheDataFrameIndex_, length, bufDesc.buffer != nullptr, fullCacheData_ != nullptr,
349             fullCacheData_->buffer != nullptr, streamID_);
350     }
351 }
352 
OnFirstFrameWriting(uint64_t latency)353 void CacheBuffer::OnFirstFrameWriting(uint64_t latency)
354 {
355     MEDIA_LOGI("CacheBuffer::OnFirstFrameWriting, streamID_:%{public}d", streamID_);
356     CHECK_AND_RETURN_LOG(frameWriteCallback_ != nullptr, "frameWriteCallback is null.");
357     frameWriteCallback_->OnFirstAudioFrameWritingCallback(latency);
358 }
359 
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)360 void CacheBuffer::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
361 {
362     MEDIA_LOGI("CacheBuffer::OnInterrupt, streamID_:%{public}d, eventType:%{public}d, forceType:%{public}d,"
363         "hintType:%{public}d", streamID_, interruptEvent.eventType, interruptEvent.forceType,
364         interruptEvent.hintType);
365     if (interruptEvent.hintType == AudioStandard::InterruptHint::INTERRUPT_HINT_PAUSE ||
366         interruptEvent.hintType == AudioStandard::InterruptHint::INTERRUPT_HINT_STOP) {
367         MEDIA_LOGI("CacheBuffer::OnInterrupt, interrupt cacheBuffer, streamID_:%{public}d", streamID_);
368         int32_t streamIDInterrupt = streamID_;
369         ThreadPool::Task cacheBufferInterruptTask = [this, streamIDInterrupt] { this->Stop(streamIDInterrupt); };
370         if (auto ptr = cacheBufferStopThreadPool_.lock()) {
371             ptr->AddTask(cacheBufferInterruptTask);
372         }
373     }
374 }
375 
OnStateChange(const AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)376 void CacheBuffer::OnStateChange(const AudioStandard::RendererState state,
377     const AudioStandard::StateChangeCmdType cmdType)
378 {
379     MEDIA_LOGI("CacheBuffer::OnStateChange, state:%{public}d", state);
380 }
381 
Stop(const int32_t streamID)382 int32_t CacheBuffer::Stop(const int32_t streamID)
383 {
384     MediaTrace trace("CacheBuffer::Stop");
385     std::lock_guard lock(cacheBufferLock_);
386     CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID_.");
387     MEDIA_LOGI("CacheBuffer::Stop streamID:%{public}d", streamID_);
388     if (audioRenderer_ != nullptr && isRunning_.load()) {
389         isRunning_.store(false);
390         SoundPoolXCollie soundPoolXCollie("audioRenderer::Pause or Stop time out",
391             [](void *) {
392                 MEDIA_LOGI("audioRenderer::Pause or Stop time out");
393             });
394         if (audioRenderer_->IsFastRenderer()) {
395             MEDIA_LOGI("audioRenderer fast renderer pause.");
396             audioRenderer_->Pause();
397             audioRenderer_->Flush();
398         } else {
399             MEDIA_LOGI("audioRenderer normal stop.");
400             audioRenderer_->Stop();
401         }
402         soundPoolXCollie.CancelXCollieTimer();
403         cacheDataFrameIndex_ = 0;
404         havePlayedCount_ = 0;
405         if (callback_ != nullptr) {
406             MEDIA_LOGI("cachebuffer callback_ OnPlayFinished.");
407             callback_->OnPlayFinished(streamID_);
408         }
409         if (cacheBufferCallback_ != nullptr) {
410             MEDIA_LOGI("cachebuffer cacheBufferCallback_ OnPlayFinished.");
411             cacheBufferCallback_->OnPlayFinished(streamID_);
412         }
413     }
414     return MSERR_OK;
415 }
416 
SetVolume(const int32_t streamID,const float leftVolume,const float rightVolume)417 int32_t CacheBuffer::SetVolume(const int32_t streamID, const float leftVolume, const float rightVolume)
418 {
419     std::lock_guard lock(cacheBufferLock_);
420     int32_t ret = MSERR_OK;
421     if (streamID == streamID_) {
422         if (audioRenderer_ != nullptr) {
423             // audio cannot support left & right volume, all use left volume.
424             (void) rightVolume;
425             ret = audioRenderer_->SetVolume(leftVolume);
426         }
427     }
428     return ret;
429 }
430 
SetRate(const int32_t streamID,const AudioStandard::AudioRendererRate renderRate)431 int32_t CacheBuffer::SetRate(const int32_t streamID, const AudioStandard::AudioRendererRate renderRate)
432 {
433     std::lock_guard lock(cacheBufferLock_);
434     int32_t ret = MSERR_INVALID_VAL;
435     if (streamID == streamID_) {
436         if (audioRenderer_ != nullptr) {
437             ret = audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(renderRate));
438         }
439     }
440     return ret;
441 }
442 
SetPriority(const int32_t streamID,const int32_t priority)443 int32_t CacheBuffer::SetPriority(const int32_t streamID, const int32_t priority)
444 {
445     std::lock_guard lock(cacheBufferLock_);
446     if (streamID == streamID_) {
447         priority_ = priority;
448     }
449     return MSERR_OK;
450 }
451 
SetLoop(const int32_t streamID,const int32_t loop)452 int32_t CacheBuffer::SetLoop(const int32_t streamID, const int32_t loop)
453 {
454     std::lock_guard lock(cacheBufferLock_);
455     if (streamID == streamID_) {
456         loop_ = loop;
457         havePlayedCount_ = 0;
458     }
459     return MSERR_OK;
460 }
461 
SetParallelPlayFlag(const int32_t streamID,const bool parallelPlayFlag)462 int32_t CacheBuffer::SetParallelPlayFlag(const int32_t streamID, const bool parallelPlayFlag)
463 {
464     std::lock_guard lock(cacheBufferLock_);
465     if (streamID == streamID_) {
466         MEDIA_LOGI("CacheBuffer parallelPlayFlag:%{public}d.", parallelPlayFlag);
467         if (audioRenderer_ != nullptr) {
468             audioRenderer_->SetParallelPlayFlag(parallelPlayFlag);
469         }
470     }
471     return MSERR_OK;
472 }
473 
Release()474 int32_t CacheBuffer::Release()
475 {
476     MediaTrace trace("CacheBuffer::Release");
477     // Define a temporary variable.Let audioRenderer_ to audioRenderer can protect audioRenderer_ concurrently
478     // modified.So will not cause null pointers.
479     std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer;
480     {
481         std::lock_guard lock(cacheBufferLock_);
482         audioRenderer = std::move(audioRenderer_);
483         audioRenderer_ = nullptr;
484         isRunning_.store(false);
485     }
486 
487     MEDIA_LOGI("CacheBuffer::Release start, streamID:%{public}d", streamID_);
488     // Use audioRenderer to release and don't lock, so it will not cause dead lock. if here locked, audioRenderer
489     // will wait callback thread stop, and the callback thread can't get the lock, it will cause dead lock
490     if (audioRenderer != nullptr) {
491         SoundPoolXCollie soundPoolXCollie("Release audioRenderer::Stop time out",
492             [](void *) {
493                 MEDIA_LOGI("Release audioRenderer::Stop time out");
494             });
495         audioRenderer->Stop();
496         soundPoolXCollie.CancelXCollieTimer();
497         SoundPoolXCollie soundPoolXCollieRelease("Release audioRenderer::Release time out",
498         [](void *) {
499             MEDIA_LOGI("Release audioRenderer::Release time out");
500         });
501         audioRenderer->Release();
502         soundPoolXCollieRelease.CancelXCollieTimer();
503         audioRenderer = nullptr;
504     }
505 
506     std::lock_guard lock(cacheBufferLock_);
507     if (!cacheData_.empty()) cacheData_.clear();
508     if (fullCacheData_ != nullptr) fullCacheData_.reset();
509     if (callback_ != nullptr) callback_.reset();
510     if (cacheBufferCallback_ != nullptr) cacheBufferCallback_.reset();
511     if (frameWriteCallback_ != nullptr) frameWriteCallback_.reset();
512     MEDIA_LOGI("CacheBuffer::Release end, streamID:%{public}d", streamID_);
513     return MSERR_OK;
514 }
515 
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)516 int32_t CacheBuffer::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
517 {
518     callback_ = callback;
519     return MSERR_OK;
520 }
521 
SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> & callback)522 int32_t CacheBuffer::SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
523 {
524     cacheBufferCallback_ = callback;
525     return MSERR_OK;
526 }
527 
SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & callback)528 int32_t CacheBuffer::SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> &callback)
529 {
530     frameWriteCallback_ = callback;
531     return MSERR_OK;
532 }
533 } // namespace Media
534 } // namespace OHOS
535