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