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