• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <algorithm>
17 #include "parameter.h"
18 #include "soundpool.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "stream_id_manager.h"
22 #include "audio_renderer_manager.h"
23 
24 namespace {
25     // audiorender max concurrency.
26     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "StreamIDManager"};
27     static const std::string THREAD_POOL_NAME = "OS_StreamMgr";
28     static const std::string THREAD_POOL_NAME_CACHE_BUFFER = "OS_CacheBuf";
29     static const int32_t MAX_THREADS_NUM = std::thread::hardware_concurrency() >= 4 ? 2 : 1;
30     static const int32_t ERROE_GLOBAL_ID = -1;
31 }
32 
33 namespace OHOS {
34 namespace Media {
StreamIDManager(int32_t maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)35 StreamIDManager::StreamIDManager(int32_t maxStreams,
36     AudioStandard::AudioRendererInfo audioRenderInfo) : audioRendererInfo_(audioRenderInfo), maxStreams_(maxStreams)
37 {
38     MEDIA_LOGI("Construction StreamIDManager.");
39     audioRendererInfo_.playerType = AudioStandard::PlayerType::PLAYER_TYPE_SOUND_POOL;
40 }
41 
~StreamIDManager()42 StreamIDManager::~StreamIDManager()
43 {
44     MEDIA_LOGI("Destruction StreamIDManager");
45     if (callback_ != nullptr) {
46         callback_.reset();
47     }
48     if (frameWriteCallback_ != nullptr) {
49         frameWriteCallback_.reset();
50     }
51     for (auto cacheBuffer : cacheBuffers_) {
52         if (cacheBuffer.second != nullptr) {
53             int32_t streamID = cacheBuffer.second->GetStreamID();
54             cacheBuffer.second->Stop(streamID);
55             cacheBuffer.second->Release();
56         }
57     }
58     cacheBuffers_.clear();
59     if (isStreamPlayingThreadPoolStarted_.load()) {
60         if (streamPlayingThreadPool_ != nullptr) {
61             streamPlayingThreadPool_->Stop();
62         }
63         isStreamPlayingThreadPoolStarted_.store(false);
64     }
65     if (isCacheBufferStopThreadPoolStarted_.load()) {
66         if (cacheBufferStopThreadPool_ != nullptr) {
67             cacheBufferStopThreadPool_->Stop();
68         }
69         isCacheBufferStopThreadPoolStarted_.store(false);
70     }
71 }
72 
InitThreadPool()73 int32_t StreamIDManager::InitThreadPool()
74 {
75     if (isStreamPlayingThreadPoolStarted_.load()) {
76         return MSERR_OK;
77     }
78     streamPlayingThreadPool_ = std::make_unique<ThreadPool>(THREAD_POOL_NAME);
79     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
80         "Failed to obtain playing ThreadPool");
81     if (maxStreams_ > MAX_PLAY_STREAMS_NUMBER) {
82         maxStreams_ = MAX_PLAY_STREAMS_NUMBER;
83         MEDIA_LOGI("more than max play stream number, align to max play strem number.");
84     }
85     if (maxStreams_ < MIN_PLAY_STREAMS_NUMBER) {
86         maxStreams_ = MIN_PLAY_STREAMS_NUMBER;
87         MEDIA_LOGI("less than min play stream number, align to min play strem number.");
88     }
89     MEDIA_LOGI("stream playing thread pool maxStreams_:%{public}d", maxStreams_);
90     // For stream priority logic, thread num need align to task num.
91     streamPlayingThreadPool_->Start(maxStreams_);
92     streamPlayingThreadPool_->SetMaxTaskNum(maxStreams_);
93     isStreamPlayingThreadPoolStarted_.store(true);
94 
95     cacheBufferStopThreadPool_ = std::make_shared<ThreadPool>(THREAD_POOL_NAME_CACHE_BUFFER);
96     CHECK_AND_RETURN_RET_LOG(cacheBufferStopThreadPool_ != nullptr, MSERR_INVALID_VAL,
97         "Failed to obtain stop ThreadPool");
98     cacheBufferStopThreadPool_->Start(CACHE_BUFFER_THREAD_NUMBER);
99     cacheBufferStopThreadPool_->SetMaxTaskNum(CACHE_BUFFER_THREAD_NUMBER);
100     isCacheBufferStopThreadPoolStarted_.store(true);
101 
102     OHOS::Media::AudioRendererManager::GetInstance().SetStreamIDManager(weak_from_this());
103     return MSERR_OK;
104 }
105 
GetGlobalId(int32_t soundId)106 int32_t StreamIDManager::GetGlobalId(int32_t soundId)
107 {
108     std::lock_guard lock(globalIdMutex_);
109     for (auto it = globalIdVector_.begin(); it !=  globalIdVector_.end();) {
110         if (it->first == soundId) {
111             return it->second;
112         } else {
113             ++it;
114         }
115     }
116     return ERROE_GLOBAL_ID;
117 }
118 
DelGlobalId(int32_t globalId)119 void StreamIDManager::DelGlobalId(int32_t globalId)
120 {
121     std::lock_guard lock(globalIdMutex_);
122     for (auto it = globalIdVector_.begin(); it !=  globalIdVector_.end();) {
123         if (it->second == globalId) {
124             globalIdVector_.erase(it);
125             break;
126         } else {
127             ++it;
128         }
129     }
130 }
131 
SetGlobalId(int32_t soundId,int32_t globalId)132 void StreamIDManager::SetGlobalId(int32_t soundId, int32_t globalId)
133 {
134     std::lock_guard lock(globalIdMutex_);
135     globalIdVector_.push_back(std::make_pair(soundId, globalId));
136 }
137 
DelSoundId(int32_t soundId)138 void StreamIDManager::DelSoundId(int32_t soundId)
139 {
140     std::lock_guard lock(globalIdMutex_);
141     for (auto it = globalIdVector_.begin(); it !=  globalIdVector_.end();) {
142         if (it->first == soundId) {
143             OHOS::Media::AudioRendererManager::GetInstance().DelAudioRenderer(it->second);
144             it = globalIdVector_.erase(it);
145         } else {
146             ++it;
147         }
148     }
149 }
150 
Play(std::shared_ptr<SoundParser> & soundParser,PlayParams & playParameters)151 int32_t StreamIDManager::Play(std::shared_ptr<SoundParser> &soundParser, PlayParams &playParameters)
152 {
153     MediaTrace trace("StreamIDManager::Play");
154     CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid soundParser.");
155     int32_t soundID = soundParser->GetSoundID();
156     int32_t streamID = GetFreshStreamID(soundID, playParameters);
157     {
158         std::lock_guard lock(streamIDManagerLock_);
159         if (streamID <= 0) {
160             do {
161                 nextStreamID_ = nextStreamID_ == INT32_MAX ? 1 : nextStreamID_ + 1;
162             } while (FindCacheBuffer(nextStreamID_) != nullptr);
163             streamID = nextStreamID_;
164             std::shared_ptr<AudioBufferEntry> cacheData;
165             soundParser->GetSoundData(cacheData);
166             size_t cacheDataTotalSize = soundParser->GetSoundDataTotalSize();
167             auto cacheBuffer = std::make_shared<OHOS::Media::CacheBuffer>(soundParser->GetSoundTrackFormat(),
168                      soundID, streamID, cacheBufferStopThreadPool_);
169             CHECK_AND_RETURN_RET_LOG(cacheBuffer != nullptr, -1, "failed to create cache buffer");
170             cacheBuffer->SetSoundData(cacheData, cacheDataTotalSize);
171             cacheBuffer->SetManager(weak_from_this());
172             CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, MSERR_INVALID_VAL, "Invalid callback.");
173             cacheBuffer->SetCallback(callback_);
174             cacheBufferCallback_ = std::make_shared<CacheBufferCallBack>(weak_from_this());
175             CHECK_AND_RETURN_RET_LOG(cacheBufferCallback_ != nullptr, MSERR_INVALID_VAL,
176                 "Invalid cachebuffer callback");
177             cacheBuffer->SetCacheBufferCallback(cacheBufferCallback_);
178             if (frameWriteCallback_ != nullptr) {
179                 cacheBuffer->SetFrameWriteCallback(frameWriteCallback_);
180             }
181             std::chrono::microseconds duration(soundParser->GetSourceDuration());
182             int64_t durationMs = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
183             cacheBuffer->SetSourceDuration(durationMs);
184             cacheBuffers_.emplace(streamID, cacheBuffer);
185         }
186     }
187     MEDIA_LOGI("StreamIDManager::SetPlay start soundID:%{public}d, streamID:%{public}d", soundID, streamID);
188     int32_t result = SetPlay(soundID, streamID, playParameters);
189     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, errorStreamId, "Invalid SetPlay");
190     return streamID;
191 }
192 
SetPlay(const int32_t soundID,const int32_t streamID,const PlayParams playParameters)193 int32_t StreamIDManager::SetPlay(const int32_t soundID, const int32_t streamID, const PlayParams playParameters)
194 {
195     MediaTrace trace("StreamIDManager::SetPlay");
196     if (!isStreamPlayingThreadPoolStarted_.load()) {
197         InitThreadPool();
198     }
199 
200     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
201         "Failed to obtain stream play threadpool.");
202     // CacheBuffer must prepare before play.
203     std::shared_ptr<CacheBuffer> freshCacheBuffer;
204     {
205         std::lock_guard lock(streamIDManagerLock_);
206         freshCacheBuffer = FindCacheBuffer(streamID);
207     }
208     CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid fresh cache buffer");
209     int32_t result = freshCacheBuffer->PreparePlay(audioRendererInfo_, playParameters);
210     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, MSERR_INVALID_VAL, "Invalid PreparePlay");
211     int32_t tempMaxStream = maxStreams_;
212     MEDIA_LOGI("StreamIDManager cur task num:%{public}zu, maxStreams_:%{public}d",
213         playingStreamIDs_.size(), maxStreams_);
214     if (playingStreamIDs_.size() < static_cast<size_t>(tempMaxStream)) {
215         AddPlayTask(streamID, playParameters);
216     } else {
217         int32_t playingStreamID = playingStreamIDs_.back();
218         std::shared_ptr<CacheBuffer> playingCacheBuffer;
219         {
220             std::lock_guard lock(streamIDManagerLock_);
221             playingCacheBuffer = FindCacheBuffer(playingStreamID);
222         }
223         CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid fresh cache buffer");
224         CHECK_AND_RETURN_RET_LOG(playingCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid playingCacheBuffer");
225         MEDIA_LOGI("StreamIDManager fresh sound priority:%{public}d, playing stream priority:%{public}d",
226             freshCacheBuffer->GetPriority(), playingCacheBuffer->GetPriority());
227         if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
228             MEDIA_LOGI("StreamIDManager stop playing low priority sound:%{public}d", playingStreamID);
229             playingCacheBuffer->Stop(playingStreamID);
230             MEDIA_LOGI("StreamIDManager to playing fresh streamID:%{public}d.", streamID);
231             AddPlayTask(streamID, playParameters);
232         } else {
233             std::lock_guard lock(streamIDManagerLock_);
234             MEDIA_LOGI("StreamIDManager queue will play streams, streamID:%{public}d.", streamID);
235             StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo;
236             freshStreamIDAndPlayParamsInfo.streamID = streamID;
237             freshStreamIDAndPlayParamsInfo.playParameters = playParameters;
238             QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
239         }
240     }
241     return MSERR_OK;
242 }
243 
244 // Sort in descending order
245 // 0 has the lowest priority, and the higher the value, the higher the priority
246 // The queue head has the highest value and priority
QueueAndSortPlayingStreamID(int32_t streamID)247 void StreamIDManager::QueueAndSortPlayingStreamID(int32_t streamID)
248 {
249     if (playingStreamIDs_.empty()) {
250         playingStreamIDs_.emplace_back(streamID);
251     } else {
252         bool shouldReCombinePlayingQueue = false;
253         for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
254             int32_t playingStreamID = playingStreamIDs_[i];
255             std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(streamID);
256             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
257             if (playingCacheBuffer == nullptr) {
258                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
259                 shouldReCombinePlayingQueue = true;
260                 break;
261             }
262             if (freshCacheBuffer == nullptr) {
263                 break;
264             }
265             if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
266                 playingStreamIDs_.insert(playingStreamIDs_.begin() + i, streamID);
267                 break;
268             }
269             if (playingStreamIDs_.size() >= 1 && i == playingStreamIDs_.size() - 1 &&
270                 freshCacheBuffer->GetPriority() < playingCacheBuffer->GetPriority()) {
271                 playingStreamIDs_.push_back(streamID);
272                 break;
273             }
274         }
275         if (shouldReCombinePlayingQueue) {
276             QueueAndSortPlayingStreamID(streamID);
277         }
278     }
279 }
280 
281 // Sort in descending order.
282 // 0 has the lowest priority, and the higher the value, the higher the priority
283 // The queue head has the highest value and priority
QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)284 void StreamIDManager::QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)
285 {
286     if (willPlayStreamInfos_.empty()) {
287         willPlayStreamInfos_.emplace_back(freshStreamIDAndPlayParamsInfo);
288     } else {
289         bool shouldReCombineWillPlayQueue = false;
290         for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
291             std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(freshStreamIDAndPlayParamsInfo.streamID);
292             std::shared_ptr<CacheBuffer> willPlayCacheBuffer = FindCacheBuffer(willPlayStreamInfos_[i].streamID);
293             if (willPlayCacheBuffer == nullptr) {
294                 willPlayStreamInfos_.erase(willPlayStreamInfos_.begin() + i);
295                 shouldReCombineWillPlayQueue = true;
296                 break;
297             }
298             if (freshCacheBuffer == nullptr) {
299                 break;
300             }
301             if (freshCacheBuffer->GetPriority() >= willPlayCacheBuffer->GetPriority()) {
302                 willPlayStreamInfos_.insert(willPlayStreamInfos_.begin() + i, freshStreamIDAndPlayParamsInfo);
303                 break;
304             }
305             if (willPlayStreamInfos_.size() >= 1 && i == willPlayStreamInfos_.size() - 1 &&
306                 freshCacheBuffer->GetPriority() < willPlayCacheBuffer->GetPriority()) {
307                 willPlayStreamInfos_.push_back(freshStreamIDAndPlayParamsInfo);
308                 break;
309             }
310         }
311         if (shouldReCombineWillPlayQueue) {
312             QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
313         }
314     }
315 }
316 
AddPlayTask(const int32_t streamID,const PlayParams playParameters)317 int32_t StreamIDManager::AddPlayTask(const int32_t streamID, const PlayParams playParameters)
318 {
319     ThreadPool::Task streamPlayTask = [this, streamID] { this->DoPlay(streamID); };
320     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
321         "Failed to obtain playing ThreadPool");
322     CHECK_AND_RETURN_RET_LOG(streamPlayTask != nullptr, MSERR_INVALID_VAL, "Failed to obtain stream play Task");
323     streamPlayingThreadPool_->AddTask(streamPlayTask);
324     std::lock_guard lock(streamIDManagerLock_);
325     QueueAndSortPlayingStreamID(streamID);
326     return MSERR_OK;
327 }
328 
DoPlay(const int32_t streamID)329 int32_t StreamIDManager::DoPlay(const int32_t streamID)
330 {
331     MEDIA_LOGI("StreamIDManager::DoPlay start streamID:%{public}d", streamID);
332     std::shared_ptr<CacheBuffer> cacheBuffer;
333     {
334         std::lock_guard lock(streamIDManagerLock_);
335         cacheBuffer = FindCacheBuffer(streamID);
336     }
337     CHECK_AND_RETURN_RET_LOG(cacheBuffer.get() != nullptr, MSERR_INVALID_VAL, "cachebuffer invalid.");
338     if (cacheBuffer->DoPlay(streamID) == MSERR_OK) {
339         MEDIA_LOGI("StreamIDManager::DoPlay success streamID:%{public}d", streamID);
340         return MSERR_OK;
341     }
342     MEDIA_LOGI("StreamIDManager::DoPlay failed streamID:%{public}d", streamID);
343     {
344         std::lock_guard lock(streamIDManagerLock_);
345         for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
346             int32_t playingStreamID = playingStreamIDs_[i];
347             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
348             if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
349                 MEDIA_LOGI("StreamIDManager::DoPlay fail erase playingStreamID:%{public}d", playingStreamID);
350                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
351                 i--;
352             }
353         }
354     }
355     return MSERR_INVALID_VAL;
356 }
357 
FindCacheBuffer(const int32_t streamID)358 std::shared_ptr<CacheBuffer> StreamIDManager::FindCacheBuffer(const int32_t streamID)
359 {
360     if (cacheBuffers_.empty()) {
361         MEDIA_LOGI("StreamIDManager::FindCacheBuffer cacheBuffers_ empty");
362         return nullptr;
363     }
364     CHECK_AND_RETURN_RET_LOG(streamID >= 0, nullptr, "streamID invalid.");
365     auto it = cacheBuffers_.find(streamID);
366     if (it != cacheBuffers_.end()) {
367         return it->second;
368     }
369     return nullptr;
370 }
371 
FindCacheBufferLock(const int32_t streamID)372 std::shared_ptr<CacheBuffer> StreamIDManager::FindCacheBufferLock(const int32_t streamID)
373 {
374     std::lock_guard lock(streamIDManagerLock_);
375     return FindCacheBuffer(streamID);
376 }
377 
GetStreamIDBySoundID(const int32_t soundID)378 int32_t StreamIDManager::GetStreamIDBySoundID(const int32_t soundID)
379 {
380     PlayParams playParameters;
381     return GetFreshStreamID(soundID, playParameters);
382 }
383 
ReorderStream(int32_t streamID,int32_t priority)384 int32_t StreamIDManager::ReorderStream(int32_t streamID, int32_t priority)
385 {
386     std::lock_guard lock(streamIDManagerLock_);
387     int32_t playingSize = static_cast<int32_t>(playingStreamIDs_.size());
388     for (int32_t i = 0; i < playingSize - 1; ++i) {
389         for (int32_t j = 0; j < playingSize - 1 - i; ++j) {
390             std::shared_ptr<CacheBuffer> left = FindCacheBuffer(playingStreamIDs_[j]);
391             std::shared_ptr<CacheBuffer> right = FindCacheBuffer(playingStreamIDs_[j + 1]);
392             if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
393                 int32_t streamIdTemp = playingStreamIDs_[j];
394                 playingStreamIDs_[j] = playingStreamIDs_[j + 1];
395                 playingStreamIDs_[j + 1] = streamIdTemp;
396             }
397         }
398     }
399     for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
400         int32_t playingStreamID = playingStreamIDs_[i];
401         MEDIA_LOGD("StreamIDManager::ReorderStream  playingStreamID:%{public}d", playingStreamID);
402     }
403 
404     int32_t willPlaySize = static_cast<int32_t>(willPlayStreamInfos_.size());
405     for (int32_t i = 0; i < willPlaySize - 1; ++i) {
406         for (int32_t j = 0; j < willPlaySize - 1 - i; ++j) {
407             std::shared_ptr<CacheBuffer> left = FindCacheBuffer(willPlayStreamInfos_[j].streamID);
408             std::shared_ptr<CacheBuffer> right = FindCacheBuffer(willPlayStreamInfos_[j + 1].streamID);
409             if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
410                 StreamIDAndPlayParamsInfo willPlayInfoTemp = willPlayStreamInfos_[j];
411                 willPlayStreamInfos_[j] = willPlayStreamInfos_[j + 1];
412                 willPlayStreamInfos_[j + 1] = willPlayInfoTemp;
413             }
414         }
415     }
416     for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
417         StreamIDAndPlayParamsInfo willPlayInfo = willPlayStreamInfos_[i];
418         MEDIA_LOGD("StreamIDManager::ReorderStream  willPlayStreamID:%{public}d", willPlayInfo.streamID);
419     }
420     return MSERR_OK;
421 }
422 
ClearStreamIDInDeque(int32_t streamID,int32_t soundID)423 int32_t StreamIDManager::ClearStreamIDInDeque(int32_t streamID, int32_t soundID)
424 {
425     {
426         std::lock_guard lock(streamIDManagerLock_);
427         for (auto it = playingStreamIDs_.begin(); it != playingStreamIDs_.end();) {
428             if (*it == streamID) {
429                 MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque playingDel streamID:%{public}d", streamID);
430                 it = playingStreamIDs_.erase(it);
431             } else {
432                 ++it;
433             }
434         }
435         for (auto it = willPlayStreamInfos_.begin(); it != willPlayStreamInfos_.end();) {
436             if (it->streamID == streamID) {
437                 MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque willPlayDel streamID:%{public}d", streamID);
438                 it = willPlayStreamInfos_.erase(it);
439             } else {
440                 ++it;
441             }
442         }
443         cacheBuffers_.erase(streamID);
444     }
445     DelSoundId(soundID);
446     return MSERR_OK;
447 }
448 
GetFreshStreamID(const int32_t soundID,PlayParams playParameters)449 int32_t StreamIDManager::GetFreshStreamID(const int32_t soundID, PlayParams playParameters)
450 {
451     int32_t streamID = 0;
452     if (cacheBuffers_.empty()) {
453         MEDIA_LOGI("StreamIDManager::GetFreshStreamID cacheBuffers_ empty");
454         return streamID;
455     }
456     for (auto cacheBuffer : cacheBuffers_) {
457         if (cacheBuffer.second == nullptr) {
458             MEDIA_LOGE("Invalid cacheBuffer, soundID:%{public}d", soundID);
459             continue;
460         }
461         if (soundID == cacheBuffer.second->GetSoundID()) {
462             streamID = cacheBuffer.second->GetStreamID();
463             MEDIA_LOGI("Have cache soundID:%{public}d, streamID:%{public}d", soundID, streamID);
464             break;
465         }
466     }
467     return streamID;
468 }
469 
OnPlayFinished()470 void StreamIDManager::OnPlayFinished()
471 {
472     {
473         std::lock_guard lock(streamIDManagerLock_);
474         for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
475             int32_t playingStreamID = playingStreamIDs_[i];
476             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
477             if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
478                 MEDIA_LOGI("StreamIDManager::OnPlayFinished erase playingStreamID:%{public}d", playingStreamID);
479                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
480                 i--;
481             }
482         }
483     }
484     if (!willPlayStreamInfos_.empty()) {
485         MEDIA_LOGI("StreamIDManager OnPlayFinished will play streams non empty, get the front.");
486         StreamIDAndPlayParamsInfo willPlayStreamInfo =  willPlayStreamInfos_.front();
487         AddPlayTask(willPlayStreamInfo.streamID, willPlayStreamInfo.playParameters);
488         std::lock_guard lock(streamIDManagerLock_);
489         willPlayStreamInfos_.pop_front();
490     }
491 }
492 
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)493 int32_t StreamIDManager::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
494 {
495     callback_ = callback;
496     return MSERR_OK;
497 }
498 
SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & callback)499 int32_t StreamIDManager::SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> &callback)
500 {
501     frameWriteCallback_ = callback;
502     return MSERR_OK;
503 }
504 
OnLoadCompleted(int32_t soundID)505 void StreamIDManager::CacheBufferCallBack::OnLoadCompleted(int32_t soundID)
506 {
507     (void)soundID;
508 }
509 
OnPlayFinished(int32_t streamID)510 void StreamIDManager::CacheBufferCallBack::OnPlayFinished(int32_t streamID)
511 {
512     (void)streamID;
513     if (std::shared_ptr<StreamIDManager> ptr = streamIDManagerInner_.lock()) {
514         ptr->OnPlayFinished();
515     }
516 }
517 
OnError(int32_t errorCode)518 void StreamIDManager::CacheBufferCallBack::OnError(int32_t errorCode)
519 {
520     (void)errorCode;
521 }
522 
523 } // namespace Media
524 } // namespace OHOS
525