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 int32_t result = SetPlay(soundID, streamID, playParameters);
137 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, errorStreamId, "Invalid SetPlay");
138 return streamID;
139 }
140
SetPlay(const int32_t soundID,const int32_t streamID,const PlayParams playParameters)141 int32_t StreamIDManager::SetPlay(const int32_t soundID, const int32_t streamID, const PlayParams playParameters)
142 {
143 MediaTrace trace("StreamIDManager::SetPlay");
144 if (!isStreamPlayingThreadPoolStarted_.load()) {
145 InitThreadPool();
146 }
147
148 CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
149 "Failed to obtain stream play threadpool.");
150 // CacheBuffer must prepare before play.
151 std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(streamID);
152 CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid fresh cache buffer");
153 int32_t result = freshCacheBuffer->PreparePlay(streamID, audioRendererInfo_, playParameters);
154 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, MSERR_INVALID_VAL, "Invalid PreparePlay");
155 int32_t tempMaxStream = maxStreams_;
156 MEDIA_LOGI("StreamIDManager cur task num:%{public}zu, maxStreams_:%{public}d",
157 playingStreamIDs_.size(), maxStreams_);
158 if (playingStreamIDs_.size() < static_cast<size_t>(tempMaxStream)) {
159 AddPlayTask(streamID, playParameters);
160 } else {
161 int32_t playingStreamID = playingStreamIDs_.back();
162 std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
163 CHECK_AND_RETURN_RET_LOG(freshCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid fresh cache buffer");
164 CHECK_AND_RETURN_RET_LOG(playingCacheBuffer != nullptr, MSERR_INVALID_VAL, "Invalid playingCacheBuffer");
165 MEDIA_LOGI("StreamIDManager fresh sound priority:%{public}d, playing stream priority:%{public}d",
166 freshCacheBuffer->GetPriority(), playingCacheBuffer->GetPriority());
167 if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
168 MEDIA_LOGI("StreamIDManager stop playing low priority sound:%{public}d", playingStreamID);
169 playingCacheBuffer->Stop(playingStreamID);
170 MEDIA_LOGI("StreamIDManager to playing fresh streamID:%{public}d.", streamID);
171 AddPlayTask(streamID, playParameters);
172 } else {
173 std::lock_guard lock(streamIDManagerLock_);
174 MEDIA_LOGI("StreamIDManager queue will play streams, streamID:%{public}d.", streamID);
175 StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo;
176 freshStreamIDAndPlayParamsInfo.streamID = streamID;
177 freshStreamIDAndPlayParamsInfo.playParameters = playParameters;
178 QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
179 }
180 }
181 return MSERR_OK;
182 }
183
184 // Sort in descending order
185 // 0 has the lowest priority, and the higher the value, the higher the priority
186 // The queue head has the highest value and priority
QueueAndSortPlayingStreamID(int32_t streamID)187 void StreamIDManager::QueueAndSortPlayingStreamID(int32_t streamID)
188 {
189 if (playingStreamIDs_.empty()) {
190 playingStreamIDs_.emplace_back(streamID);
191 } else {
192 bool shouldReCombinePlayingQueue = false;
193 for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
194 int32_t playingStreamID = playingStreamIDs_[i];
195 std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(streamID);
196 std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
197 if (playingCacheBuffer == nullptr) {
198 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
199 shouldReCombinePlayingQueue = true;
200 break;
201 }
202 if (freshCacheBuffer == nullptr) {
203 break;
204 }
205 if (freshCacheBuffer->GetPriority() >= playingCacheBuffer->GetPriority()) {
206 playingStreamIDs_.insert(playingStreamIDs_.begin() + i, streamID);
207 break;
208 }
209 if (playingStreamIDs_.size() >= 1 && i == playingStreamIDs_.size() - 1 &&
210 freshCacheBuffer->GetPriority() < playingCacheBuffer->GetPriority()) {
211 playingStreamIDs_.push_back(streamID);
212 break;
213 }
214 }
215 if (shouldReCombinePlayingQueue) {
216 QueueAndSortPlayingStreamID(streamID);
217 }
218 }
219 }
220
221 // Sort in descending order.
222 // 0 has the lowest priority, and the higher the value, the higher the priority
223 // The queue head has the highest value and priority
QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)224 void StreamIDManager::QueueAndSortWillPlayStreamID(StreamIDAndPlayParamsInfo freshStreamIDAndPlayParamsInfo)
225 {
226 if (willPlayStreamInfos_.empty()) {
227 willPlayStreamInfos_.emplace_back(freshStreamIDAndPlayParamsInfo);
228 } else {
229 bool shouldReCombineWillPlayQueue = false;
230 for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
231 std::shared_ptr<CacheBuffer> freshCacheBuffer = FindCacheBuffer(freshStreamIDAndPlayParamsInfo.streamID);
232 std::shared_ptr<CacheBuffer> willPlayCacheBuffer = FindCacheBuffer(willPlayStreamInfos_[i].streamID);
233 if (willPlayCacheBuffer == nullptr) {
234 willPlayStreamInfos_.erase(willPlayStreamInfos_.begin() + i);
235 shouldReCombineWillPlayQueue = true;
236 break;
237 }
238 if (freshCacheBuffer == nullptr) {
239 break;
240 }
241 if (freshCacheBuffer->GetPriority() >= willPlayCacheBuffer->GetPriority()) {
242 willPlayStreamInfos_.insert(willPlayStreamInfos_.begin() + i, freshStreamIDAndPlayParamsInfo);
243 break;
244 }
245 if (willPlayStreamInfos_.size() >= 1 && i == willPlayStreamInfos_.size() - 1 &&
246 freshCacheBuffer->GetPriority() < willPlayCacheBuffer->GetPriority()) {
247 willPlayStreamInfos_.push_back(freshStreamIDAndPlayParamsInfo);
248 break;
249 }
250 }
251 if (shouldReCombineWillPlayQueue) {
252 QueueAndSortWillPlayStreamID(freshStreamIDAndPlayParamsInfo);
253 }
254 }
255 }
256
AddPlayTask(const int32_t streamID,const PlayParams playParameters)257 int32_t StreamIDManager::AddPlayTask(const int32_t streamID, const PlayParams playParameters)
258 {
259 ThreadPool::Task streamPlayTask = [this, streamID] { this->DoPlay(streamID); };
260 CHECK_AND_RETURN_RET_LOG(streamPlayingThreadPool_ != nullptr, MSERR_INVALID_VAL,
261 "Failed to obtain playing ThreadPool");
262 CHECK_AND_RETURN_RET_LOG(streamPlayTask != nullptr, MSERR_INVALID_VAL, "Failed to obtain stream play Task");
263 streamPlayingThreadPool_->AddTask(streamPlayTask);
264 std::lock_guard lock(streamIDManagerLock_);
265 QueueAndSortPlayingStreamID(streamID);
266 return MSERR_OK;
267 }
268
DoPlay(const int32_t streamID)269 int32_t StreamIDManager::DoPlay(const int32_t streamID)
270 {
271 MEDIA_LOGI("StreamIDManager::DoPlay start streamID:%{public}d", streamID);
272 std::shared_ptr<CacheBuffer> cacheBuffer = FindCacheBuffer(streamID);
273 CHECK_AND_RETURN_RET_LOG(cacheBuffer.get() != nullptr, MSERR_INVALID_VAL, "cachebuffer invalid.");
274 if (cacheBuffer->DoPlay(streamID) == MSERR_OK) {
275 MEDIA_LOGI("StreamIDManager::DoPlay success streamID:%{public}d", streamID);
276 return MSERR_OK;
277 }
278 MEDIA_LOGI("StreamIDManager::DoPlay failed streamID:%{public}d", streamID);
279 {
280 std::lock_guard lock(streamIDManagerLock_);
281 for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
282 int32_t playingStreamID = playingStreamIDs_[i];
283 std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
284 if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
285 MEDIA_LOGI("StreamIDManager::DoPlay fail erase playingStreamID:%{public}d", playingStreamID);
286 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
287 i--;
288 }
289 }
290 }
291 return MSERR_INVALID_VAL;
292 }
293
FindCacheBuffer(const int32_t streamID)294 std::shared_ptr<CacheBuffer> StreamIDManager::FindCacheBuffer(const int32_t streamID)
295 {
296 if (cacheBuffers_.empty()) {
297 MEDIA_LOGI("StreamIDManager::FindCacheBuffer cacheBuffers_ empty");
298 return nullptr;
299 }
300 CHECK_AND_RETURN_RET_LOG(streamID >= 0, nullptr, "streamID invalid.");
301 if (cacheBuffers_.find(streamID) != cacheBuffers_.end()) {
302 return cacheBuffers_.at(streamID);
303 }
304 return nullptr;
305 }
306
GetStreamIDBySoundID(const int32_t soundID)307 int32_t StreamIDManager::GetStreamIDBySoundID(const int32_t soundID)
308 {
309 PlayParams playParameters;
310 return GetFreshStreamID(soundID, playParameters);
311 }
312
ReorderStream(int32_t streamID,int32_t priority)313 int32_t StreamIDManager::ReorderStream(int32_t streamID, int32_t priority)
314 {
315 std::lock_guard lock(streamIDManagerLock_);
316 int32_t playingSize = static_cast<int32_t>(playingStreamIDs_.size());
317 for (int32_t i = 0; i < playingSize - 1; ++i) {
318 for (int32_t j = 0; j < playingSize - 1 - i; ++j) {
319 std::shared_ptr<CacheBuffer> left = FindCacheBuffer(playingStreamIDs_[j]);
320 std::shared_ptr<CacheBuffer> right = FindCacheBuffer(playingStreamIDs_[j + 1]);
321 if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
322 int32_t streamIdTemp = playingStreamIDs_[j];
323 playingStreamIDs_[j] = playingStreamIDs_[j + 1];
324 playingStreamIDs_[j + 1] = streamIdTemp;
325 }
326 }
327 }
328 for (size_t i = 0; i < playingStreamIDs_.size(); i++) {
329 int32_t playingStreamID = playingStreamIDs_[i];
330 MEDIA_LOGD("StreamIDManager::ReorderStream playingStreamID:%{public}d", playingStreamID);
331 }
332
333 int32_t willPlaySize = static_cast<int32_t>(willPlayStreamInfos_.size());
334 for (int32_t i = 0; i < willPlaySize - 1; ++i) {
335 for (int32_t j = 0; j < willPlaySize - 1 - i; ++j) {
336 std::shared_ptr<CacheBuffer> left = FindCacheBuffer(willPlayStreamInfos_[j].streamID);
337 std::shared_ptr<CacheBuffer> right = FindCacheBuffer(willPlayStreamInfos_[j + 1].streamID);
338 if (left != nullptr && right != nullptr && left->GetPriority() < right->GetPriority()) {
339 StreamIDAndPlayParamsInfo willPlayInfoTemp = willPlayStreamInfos_[j];
340 willPlayStreamInfos_[j] = willPlayStreamInfos_[j + 1];
341 willPlayStreamInfos_[j + 1] = willPlayInfoTemp;
342 }
343 }
344 }
345 for (size_t i = 0; i < willPlayStreamInfos_.size(); i++) {
346 StreamIDAndPlayParamsInfo willPlayInfo = willPlayStreamInfos_[i];
347 MEDIA_LOGD("StreamIDManager::ReorderStream willPlayStreamID:%{public}d", willPlayInfo.streamID);
348 }
349 return MSERR_OK;
350 }
351
ClearStreamIDInDeque(int32_t streamID)352 int32_t StreamIDManager::ClearStreamIDInDeque(int32_t streamID)
353 {
354 std::lock_guard lock(streamIDManagerLock_);
355 for (auto it = playingStreamIDs_.begin(); it != playingStreamIDs_.end();) {
356 if (*it == streamID) {
357 MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque playingDel streamID:%{public}d", streamID);
358 it = playingStreamIDs_.erase(it);
359 } else {
360 ++it;
361 }
362 }
363 for (auto it = willPlayStreamInfos_.begin(); it != willPlayStreamInfos_.end();) {
364 if (it->streamID == streamID) {
365 MEDIA_LOGI("StreamIDManager::ClearStreamIDInDeque willPlayDel streamID:%{public}d", streamID);
366 it = willPlayStreamInfos_.erase(it);
367 } else {
368 ++it;
369 }
370 }
371 return MSERR_OK;
372 }
373
GetFreshStreamID(const int32_t soundID,PlayParams playParameters)374 int32_t StreamIDManager::GetFreshStreamID(const int32_t soundID, PlayParams playParameters)
375 {
376 int32_t streamID = 0;
377 if (cacheBuffers_.empty()) {
378 MEDIA_LOGI("StreamIDManager::GetFreshStreamID cacheBuffers_ empty");
379 return streamID;
380 }
381 for (auto cacheBuffer : cacheBuffers_) {
382 if (cacheBuffer.second == nullptr) {
383 MEDIA_LOGE("Invalid cacheBuffer, soundID:%{public}d", soundID);
384 continue;
385 }
386 if (soundID == cacheBuffer.second->GetSoundID()) {
387 streamID = cacheBuffer.second->GetStreamID();
388 MEDIA_LOGI("Have cache soundID:%{public}d, streamID:%{public}d", soundID, streamID);
389 break;
390 }
391 }
392 return streamID;
393 }
394
OnPlayFinished()395 void StreamIDManager::OnPlayFinished()
396 {
397 {
398 std::lock_guard lock(streamIDManagerLock_);
399 for (int32_t i = 0; i < static_cast<int32_t>(playingStreamIDs_.size()); i++) {
400 int32_t playingStreamID = playingStreamIDs_[i];
401 std::shared_ptr<CacheBuffer> playingCacheBuffer = FindCacheBuffer(playingStreamID);
402 if (playingCacheBuffer != nullptr && !playingCacheBuffer->IsRunning()) {
403 MEDIA_LOGI("StreamIDManager::OnPlayFinished erase playingStreamID:%{public}d", playingStreamID);
404 playingStreamIDs_.erase(playingStreamIDs_.begin() + i);
405 i--;
406 }
407 }
408 }
409 if (!willPlayStreamInfos_.empty()) {
410 MEDIA_LOGI("StreamIDManager OnPlayFinished will play streams non empty, get the front.");
411 StreamIDAndPlayParamsInfo willPlayStreamInfo = willPlayStreamInfos_.front();
412 AddPlayTask(willPlayStreamInfo.streamID, willPlayStreamInfo.playParameters);
413 std::lock_guard lock(streamIDManagerLock_);
414 willPlayStreamInfos_.pop_front();
415 }
416 }
417
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)418 int32_t StreamIDManager::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
419 {
420 callback_ = callback;
421 return MSERR_OK;
422 }
423
SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & callback)424 int32_t StreamIDManager::SetFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> &callback)
425 {
426 frameWriteCallback_ = callback;
427 return MSERR_OK;
428 }
429
OnLoadCompleted(int32_t soundID)430 void StreamIDManager::CacheBufferCallBack::OnLoadCompleted(int32_t soundID)
431 {
432 (void)soundID;
433 }
434
OnPlayFinished(int32_t streamID)435 void StreamIDManager::CacheBufferCallBack::OnPlayFinished(int32_t streamID)
436 {
437 (void)streamID;
438 if (std::shared_ptr<StreamIDManager> ptr = streamIDManagerInner_.lock()) {
439 ptr->OnPlayFinished();
440 }
441 }
442
OnError(int32_t errorCode)443 void StreamIDManager::CacheBufferCallBack::OnError(int32_t errorCode)
444 {
445 (void)errorCode;
446 }
447
448 } // namespace Media
449 } // namespace OHOS
450