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 
23 namespace {
24     // audiorender max concurrency.
25     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "StreamIDManager"};
26     static const std::string THREAD_POOL_NAME = "OS_StreamMgr";
27     static const std::string THREAD_POOL_NAME_CACHE_BUFFER = "OS_CacheBuf";
28     static const int32_t MAX_THREADS_NUM = std::thread::hardware_concurrency() >= 4 ? 2 : 1;
29 }
30 
31 namespace OHOS {
32 namespace Media {
StreamIDManager(int32_t maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)33 StreamIDManager::StreamIDManager(int32_t maxStreams,
34     AudioStandard::AudioRendererInfo audioRenderInfo) : audioRendererInfo_(audioRenderInfo), maxStreams_(maxStreams)
35 {
36     MEDIA_LOGI("Construction StreamIDManager.");
37     InitThreadPool();
38 }
39 
~StreamIDManager()40 StreamIDManager::~StreamIDManager()
41 {
42     MEDIA_LOGI("Destruction StreamIDManager");
43     if (callback_ != nullptr) {
44         callback_.reset();
45     }
46     if (frameWriteCallback_ != nullptr) {
47         frameWriteCallback_.reset();
48     }
49     for (auto cacheBuffer : cacheBuffers_) {
50         if (cacheBuffer.second != nullptr) {
51             int32_t streamID = cacheBuffer.second->GetStreamID();
52             cacheBuffer.second->Stop(streamID);
53             cacheBuffer.second->Release();
54         }
55     }
56     cacheBuffers_.clear();
57     if (isStreamPlayingThreadPoolStarted_.load()) {
58         if (streamPlayingThreadPool_ != nullptr) {
59             streamPlayingThreadPool_->Stop();
60         }
61         isStreamPlayingThreadPoolStarted_.store(false);
62     }
63     if (isCacheBufferStopThreadPoolStarted_.load()) {
64         if (cacheBufferStopThreadPool_ != nullptr) {
65             cacheBufferStopThreadPool_->Stop();
66         }
67         isCacheBufferStopThreadPoolStarted_.store(false);
68     }
69 }
70 
InitThreadPool()71 int32_t StreamIDManager::InitThreadPool()
72 {
73     if (isStreamPlayingThreadPoolStarted_.load()) {
74         return MSERR_OK;
75     }
76     streamPlayingThreadPool_ = std::make_unique<ThreadPool>(THREAD_POOL_NAME);
77     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
78         "Failed to obtain playing ThreadPool");
79     if (maxStreams_ > MAX_PLAY_STREAMS_NUMBER) {
80         maxStreams_ = MAX_PLAY_STREAMS_NUMBER;
81         MEDIA_LOGI("more than max play stream number, align to max play strem number.");
82     }
83     if (maxStreams_ < MIN_PLAY_STREAMS_NUMBER) {
84         maxStreams_ = MIN_PLAY_STREAMS_NUMBER;
85         MEDIA_LOGI("less than min play stream number, align to min play strem number.");
86     }
87     MEDIA_LOGI("stream playing thread pool maxStreams_:%{public}d", maxStreams_);
88     // For stream priority logic, thread num need align to task num.
89     streamPlayingThreadPool_->Start(maxStreams_);
90     streamPlayingThreadPool_->SetMaxTaskNum(maxStreams_);
91     isStreamPlayingThreadPoolStarted_.store(true);
92 
93     cacheBufferStopThreadPool_ = std::make_shared<ThreadPool>(THREAD_POOL_NAME_CACHE_BUFFER);
94     cacheBufferStopThreadPool_->Start(CACHE_BUFFER_THREAD_NUMBER);
95     cacheBufferStopThreadPool_->SetMaxTaskNum(CACHE_BUFFER_THREAD_NUMBER);
96     isCacheBufferStopThreadPoolStarted_.store(true);
97 
98     return MSERR_OK;
99 }
100 
Play(std::shared_ptr<SoundParser> soundParser,PlayParams playParameters)101 int32_t StreamIDManager::Play(std::shared_ptr<SoundParser> soundParser, PlayParams playParameters)
102 {
103     MediaTrace trace("StreamIDManager::Play");
104     CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid soundParser.");
105     int32_t soundID = soundParser->GetSoundID();
106     int32_t streamID = GetFreshStreamID(soundID, playParameters);
107     {
108         std::lock_guard lock(streamIDManagerLock_);
109         if (streamID <= 0) {
110             do {
111                 nextStreamID_ = nextStreamID_ == INT32_MAX ? 1 : nextStreamID_ + 1;
112             } while (FindCacheBuffer(nextStreamID_) != nullptr);
113             streamID = nextStreamID_;
114             std::deque<std::shared_ptr<AudioBufferEntry>> cacheData;
115             soundParser->GetSoundData(cacheData);
116             size_t cacheDataTotalSize = soundParser->GetSoundDataTotalSize();
117             MEDIA_LOGI("cacheData size:%{public}zu , cacheDataTotalSize:%{public}zu",
118                 cacheData.size(), cacheDataTotalSize);
119             auto cacheBuffer =
120                 std::make_shared<CacheBuffer>(soundParser->GetSoundTrackFormat(), cacheData, cacheDataTotalSize,
121                      soundID, streamID, cacheBufferStopThreadPool_);
122             CHECK_AND_RETURN_RET_LOG(cacheBuffer != nullptr, -1, "failed to create cache buffer");
123             CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, MSERR_INVALID_VAL, "Invalid callback.");
124             cacheBuffer->SetCallback(callback_);
125             cacheBufferCallback_ = std::make_shared<CacheBufferCallBack>(weak_from_this());
126             CHECK_AND_RETURN_RET_LOG(cacheBufferCallback_ != nullptr, MSERR_INVALID_VAL,
127                 "Invalid cachebuffer callback");
128             cacheBuffer->SetCacheBufferCallback(cacheBufferCallback_);
129             if (frameWriteCallback_ != nullptr) {
130                 cacheBuffer->SetFrameWriteCallback(frameWriteCallback_);
131             }
132             cacheBuffers_.emplace(streamID, cacheBuffer);
133         }
134     }
135     MEDIA_LOGI("StreamIDManager::SetPlay start soundID:%{public}d, streamID:%{public}d", soundID, streamID);
136     SetPlay(soundID, streamID, playParameters);
137     return streamID;
138 }
139 
SetPlay(const int32_t soundID,const int32_t streamID,const PlayParams playParameters)140 int32_t StreamIDManager::SetPlay(const int32_t soundID, const int32_t streamID, const PlayParams playParameters)
141 {
142     MediaTrace trace("StreamIDManager::SetPlay");
143     if (!isStreamPlayingThreadPoolStarted_.load()) {
144         InitThreadPool();
145     }
146 
147     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
148         "Failed to obtain stream play threadpool.");
149     // CacheBuffer must prepare before play.
150     std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(streamID);
151     CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, -1, "Invalid fresh cache buffer");
152     freshCacheBuffer->PreparePlay(streamID, audioRendererInfo_, playParameters);
153     int32_t tempMaxStream = maxStreams_;
154     MEDIA_LOGI("StreamIDManager cur task num:%{public}zu, maxStreams_:%{public}d",
155         playingStreamIDs_.size(), maxStreams_);
156     if (playingStreamIDs_.size() < static_cast<size_t>(tempMaxStream)) {
157         AddPlayTask(streamID, playParameters);
158     } else {
159         int32_t playingStreamID = playingStreamIDs_.back();
160         std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
161         CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, -1, "Invalid fresh cache buffer");
162         CHECK_AND_RETURN_RET_LOG(playingCacheBuffer != nullptr, -1, "Invalid playingCacheBuffer");
163         MEDIA_LOGI("StreamIDManager fresh sound priority:%{public}d, playing stream priority:%{public}d",
164             freshCacheBuffer->GetPriority(), playingCacheBuffer->GetPriority());
165         if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
166             MEDIA_LOGI("StreamIDManager stop playing low priority sound:%{public}d", playingStreamID);
167             playingCacheBuffer->Stop(playingStreamID);
168             MEDIA_LOGI("StreamIDManager to playing fresh streamID:%{public}d.", streamID);
169             AddPlayTask(streamID, playParameters);
170         } else {
171             std::lock_guard lock(streamIDManagerLock_);
172             MEDIA_LOGI("StreamIDManager queue will play streams, streamID:%{public}d.", streamID);
173             StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo;
174             freshStreamIDAndPlayParamsInfo.streamID = streamID;
175             freshStreamIDAndPlayParamsInfo.playParameters = playParameters;
176             QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
177         }
178     }
179     for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
180         int32_t playingStreamID = playingStreamIDs_[i];
181         MEDIA_LOGD("StreamIDManager::SetPlay  playingStreamID:%{public}d", playingStreamID);
182     }
183     for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
184         StreamIDAndPlayParamsInfo willPlayInfo = willPlayStreamInfos_[i];
185         MEDIA_LOGD("StreamIDManager::SetPlay  willPlayStreamID:%{public}d", willPlayInfo.streamID);
186     }
187     return MSERR_OK;
188 }
189 
190 // Sort in descending order
191 // 0 has the lowest priority, and the higher the value, the higher the priority
192 // The queue head has the highest value and priority
QueueAndSortPlayingStreamID(int32_t streamID)193 void StreamIDManager::QueueAndSortPlayingStreamID(int32_t streamID)
194 {
195     if (playingStreamIDs_.empty()) {
196         playingStreamIDs_.emplace_back(streamID);
197     } else {
198         bool shouldReCombinePlayingQueue = false;
199         for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
200             int32_t playingStreamID = playingStreamIDs_[i];
201             std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(streamID);
202             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
203             if (playingCacheBuffer == nullptr) {
204                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
205                 shouldReCombinePlayingQueue = true;
206                 break;
207             }
208             if (freshCacheBuffer == nullptr) {
209                 break;
210             }
211             if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
212                 playingStreamIDs_.insert(playingStreamIDs_.begin() + i, streamID);
213                 break;
214             }
215             if (playingStreamIDs_.size() >= 1 && i == playingStreamIDs_.size() - 1 &&
216                 freshCacheBuffer->GetPriority() < playingCacheBuffer->GetPriority()) {
217                 playingStreamIDs_.push_back(streamID);
218                 break;
219             }
220         }
221         if (shouldReCombinePlayingQueue) {
222             QueueAndSortPlayingStreamID(streamID);
223         }
224     }
225 }
226 
227 // Sort in descending order.
228 // 0 has the lowest priority, and the higher the value, the higher the priority
229 // The queue head has the highest value and priority
QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)230 void StreamIDManager::QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)
231 {
232     if (willPlayStreamInfos_.empty()) {
233         willPlayStreamInfos_.emplace_back(freshStreamIDAndPlayParamsInfo);
234     } else {
235         bool shouldReCombineWillPlayQueue = false;
236         for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
237             std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(freshStreamIDAndPlayParamsInfo.streamID);
238             std::shared_ptr<CacheBuffer> willPlayCacheBuffer = FindCacheBuffer(willPlayStreamInfos_[i].streamID);
239             if (willPlayCacheBuffer == nullptr) {
240                 willPlayStreamInfos_.erase(willPlayStreamInfos_.begin() + i);
241                 shouldReCombineWillPlayQueue = true;
242                 break;
243             }
244             if (freshCacheBuffer == nullptr) {
245                 break;
246             }
247             if (freshCacheBuffer->GetPriority() >= willPlayCacheBuffer->GetPriority()) {
248                 willPlayStreamInfos_.insert(willPlayStreamInfos_.begin() + i, freshStreamIDAndPlayParamsInfo);
249                 break;
250             }
251             if (willPlayStreamInfos_.size() >= 1 && i == willPlayStreamInfos_.size() - 1 &&
252                 freshCacheBuffer->GetPriority() < willPlayCacheBuffer->GetPriority()) {
253                 willPlayStreamInfos_.push_back(freshStreamIDAndPlayParamsInfo);
254                 break;
255             }
256         }
257         if (shouldReCombineWillPlayQueue) {
258             QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
259         }
260     }
261 }
262 
AddPlayTask(const int32_t streamID,const PlayParams playParameters)263 int32_t StreamIDManager::AddPlayTask(const int32_t streamID, const PlayParams playParameters)
264 {
265     ThreadPool::Task streamPlayTask = [this, streamID] { this->DoPlay(streamID); };
266     CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
267         "Failed to obtain playing ThreadPool");
268     CHECK_AND_RETURN_RET_LOG(streamPlayTask != nullptr, MSERR_INVALID_VAL, "Failed to obtain stream play Task");
269     streamPlayingThreadPool_->AddTask(streamPlayTask);
270     std::lock_guard lock(streamIDManagerLock_);
271     QueueAndSortPlayingStreamID(streamID);
272     return MSERR_OK;
273 }
274 
DoPlay(const int32_t streamID)275 int32_t StreamIDManager::DoPlay(const int32_t streamID)
276 {
277     MEDIA_LOGI("StreamIDManager::DoPlay start streamID:%{public}d", streamID);
278     std::shared_ptr<CacheBuffer> cacheBuffer = FindCacheBuffer(streamID);
279     CHECK_AND_RETURN_RET_LOG(cacheBuffer.get() != nullptr, MSERR_INVALID_VAL, "cachebuffer invalid.");
280     if (cacheBuffer->DoPlay(streamID) == MSERR_OK) {
281         MEDIA_LOGI("StreamIDManager::DoPlay success streamID:%{public}d", streamID);
282         return MSERR_OK;
283     }
284     MEDIA_LOGI("StreamIDManager::DoPlay failed streamID:%{public}d", streamID);
285     {
286         std::lock_guard lock(streamIDManagerLock_);
287         for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
288             int32_t playingStreamID = playingStreamIDs_[i];
289             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
290             if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
291                 MEDIA_LOGI("StreamIDManager::DoPlay fail erase playingStreamID:%{public}d", playingStreamID);
292                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
293                 i--;
294             }
295         }
296     }
297     return MSERR_INVALID_VAL;
298 }
299 
FindCacheBuffer(const int32_t streamID)300 std::shared_ptr<CacheBuffer> StreamIDManager::FindCacheBuffer(const int32_t streamID)
301 {
302     if (cacheBuffers_.empty()) {
303         MEDIA_LOGI("StreamIDManager::FindCacheBuffer cacheBuffers_ empty");
304         return nullptr;
305     }
306     CHECK_AND_RETURN_RET_LOG(streamID >= 0, nullptr, "streamID invalid.");
307     if (cacheBuffers_.find(streamID) != cacheBuffers_.end()) {
308         return cacheBuffers_.at(streamID);
309     }
310     return nullptr;
311 }
312 
GetStreamIDBySoundID(const int32_t soundID)313 int32_t StreamIDManager::GetStreamIDBySoundID(const int32_t soundID)
314 {
315     PlayParams playParameters;
316     return GetFreshStreamID(soundID, playParameters);
317 }
318 
ReorderStream(int32_t streamID,int32_t priority)319 int32_t StreamIDManager::ReorderStream(int32_t streamID, int32_t priority)
320 {
321     std::lock_guard lock(streamIDManagerLock_);
322     int32_t playingSize = static_cast<int32_t>(playingStreamIDs_.size());
323     for (int32_t i = 0; i < playingSize - 1; ++i) {
324         for (int32_t j = 0; j < playingSize - 1 - i; ++j) {
325             std::shared_ptr<CacheBuffer> left = FindCacheBuffer(playingStreamIDs_[j]);
326             std::shared_ptr<CacheBuffer> right = FindCacheBuffer(playingStreamIDs_[j + 1]);
327             if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
328                 int32_t streamIdTemp = playingStreamIDs_[j];
329                 playingStreamIDs_[j] = playingStreamIDs_[j + 1];
330                 playingStreamIDs_[j + 1] = streamIdTemp;
331             }
332         }
333     }
334     for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
335         int32_t playingStreamID = playingStreamIDs_[i];
336         MEDIA_LOGD("StreamIDManager::ReorderStream  playingStreamID:%{public}d", playingStreamID);
337     }
338 
339     int32_t willPlaySize = static_cast<int32_t>(willPlayStreamInfos_.size());
340     for (int32_t i = 0; i < willPlaySize - 1; ++i) {
341         for (int32_t j = 0; j < willPlaySize - 1 - i; ++j) {
342             std::shared_ptr<CacheBuffer> left = FindCacheBuffer(willPlayStreamInfos_[j].streamID);
343             std::shared_ptr<CacheBuffer> right = FindCacheBuffer(willPlayStreamInfos_[j + 1].streamID);
344             if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
345                 StreamIDAndPlayParamsInfo willPlayInfoTemp = willPlayStreamInfos_[j];
346                 willPlayStreamInfos_[j] = willPlayStreamInfos_[j + 1];
347                 willPlayStreamInfos_[j + 1] = willPlayInfoTemp;
348             }
349         }
350     }
351     for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
352         StreamIDAndPlayParamsInfo willPlayInfo = willPlayStreamInfos_[i];
353         MEDIA_LOGD("StreamIDManager::ReorderStream  willPlayStreamID:%{public}d", willPlayInfo.streamID);
354     }
355     return MSERR_OK;
356 }
357 
ClearStreamIDInDeque(int32_t streamID)358 int32_t StreamIDManager::ClearStreamIDInDeque(int32_t streamID)
359 {
360     std::lock_guard lock(streamIDManagerLock_);
361     for (auto it = playingStreamIDs_.begin(); it != playingStreamIDs_.end();) {
362         if (*it == streamID) {
363             MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque playingDel streamID:%{public}d", streamID);
364             it = playingStreamIDs_.erase(it);
365         } else {
366             ++it;
367         }
368     }
369     for (auto it = willPlayStreamInfos_.begin(); it != willPlayStreamInfos_.end();) {
370         if (it->streamID == streamID) {
371             MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque willPlayDel streamID:%{public}d", streamID);
372             it = willPlayStreamInfos_.erase(it);
373         } else {
374             ++it;
375         }
376     }
377     return MSERR_OK;
378 }
379 
GetFreshStreamID(const int32_t soundID,PlayParams playParameters)380 int32_t StreamIDManager::GetFreshStreamID(const int32_t soundID, PlayParams playParameters)
381 {
382     int32_t streamID = 0;
383     if (cacheBuffers_.empty()) {
384         MEDIA_LOGI("StreamIDManager::GetFreshStreamID cacheBuffers_ empty");
385         return streamID;
386     }
387     for (auto cacheBuffer : cacheBuffers_) {
388         if (cacheBuffer.second == nullptr) {
389             MEDIA_LOGE("Invalid cacheBuffer, soundID:%{public}d", soundID);
390             continue;
391         }
392         if (soundID == cacheBuffer.second->GetSoundID()) {
393             streamID = cacheBuffer.second->GetStreamID();
394             MEDIA_LOGI("Have cache soundID:%{public}d, streamID:%{public}d", soundID, streamID);
395             break;
396         }
397     }
398     return streamID;
399 }
400 
OnPlayFinished()401 void StreamIDManager::OnPlayFinished()
402 {
403     {
404         std::lock_guard lock(streamIDManagerLock_);
405         for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
406             int32_t playingStreamID = playingStreamIDs_[i];
407             std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
408             if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
409                 MEDIA_LOGI("StreamIDManager::OnPlayFinished erase playingStreamID:%{public}d", playingStreamID);
410                 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
411                 i--;
412             }
413         }
414     }
415     if (!willPlayStreamInfos_.empty()) {
416         MEDIA_LOGI("StreamIDManager OnPlayFinished will play streams non empty, get the front.");
417         StreamIDAndPlayParamsInfo willPlayStreamInfo =  willPlayStreamInfos_.front();
418         AddPlayTask(willPlayStreamInfo.streamID, willPlayStreamInfo.playParameters);
419         std::lock_guard lock(streamIDManagerLock_);
420         willPlayStreamInfos_.pop_front();
421     }
422 }
423 
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)424 int32_t StreamIDManager::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
425 {
426     callback_ = callback;
427     return MSERR_OK;
428 }
429 
SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & callback)430 int32_t StreamIDManager::SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> &callback)
431 {
432     frameWriteCallback_ = callback;
433     return MSERR_OK;
434 }
435 
OnLoadCompleted(int32_t soundID)436 void StreamIDManager::CacheBufferCallBack::OnLoadCompleted(int32_t soundID)
437 {
438     (void)soundID;
439 }
440 
OnPlayFinished()441 void StreamIDManager::CacheBufferCallBack::OnPlayFinished()
442 {
443     if (std::shared_ptr<StreamIDManager> ptr = streamIDManagerInner_.lock()) {
444         ptr->OnPlayFinished();
445     }
446 }
447 
OnError(int32_t errorCode)448 void StreamIDManager::CacheBufferCallBack::OnError(int32_t errorCode)
449 {
450     (void)errorCode;
451 }
452 
453 } // namespace Media
454 } // namespace OHOS
455