1049e185fSopenharmony_ci/* 2049e185fSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3049e185fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4049e185fSopenharmony_ci * you may not use this file except in compliance with the License. 5049e185fSopenharmony_ci * You may obtain a copy of the License at 6049e185fSopenharmony_ci * 7049e185fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8049e185fSopenharmony_ci * 9049e185fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10049e185fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11049e185fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12049e185fSopenharmony_ci * See the License for the specific language governing permissions and 13049e185fSopenharmony_ci * limitations under the License. 14049e185fSopenharmony_ci */ 15049e185fSopenharmony_ci 16049e185fSopenharmony_ci#include <unistd.h> 17049e185fSopenharmony_ci#include "media_errors.h" 18049e185fSopenharmony_ci#include "media_log.h" 19049e185fSopenharmony_ci#include "soundpool_manager.h" 20049e185fSopenharmony_ci#include "soundpool.h" 21049e185fSopenharmony_ci 22049e185fSopenharmony_cinamespace { 23049e185fSopenharmony_ci constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "SoundPool"}; 24049e185fSopenharmony_ci} 25049e185fSopenharmony_ci 26049e185fSopenharmony_cinamespace OHOS { 27049e185fSopenharmony_cinamespace Media { 28049e185fSopenharmony_cistd::shared_ptr<ISoundPool> SoundPoolFactory::CreateSoundPool(int maxStreams, 29049e185fSopenharmony_ci AudioStandard::AudioRendererInfo audioRenderInfo) 30049e185fSopenharmony_ci{ 31049e185fSopenharmony_ci MEDIA_LOGI("SoundPoolFactory::CreateSoundPool"); 32049e185fSopenharmony_ci std::shared_ptr<SoundPool> impl; 33049e185fSopenharmony_ci if (!SoundPool::CheckInitParam(maxStreams, audioRenderInfo)) { 34049e185fSopenharmony_ci return nullptr; 35049e185fSopenharmony_ci } 36049e185fSopenharmony_ci SoundPoolManager::GetInstance().SetSoundPool(getpid(), impl); 37049e185fSopenharmony_ci SoundPoolManager::GetInstance().GetSoundPool(getpid(), impl); 38049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to get SoundPool"); 39049e185fSopenharmony_ci 40049e185fSopenharmony_ci int32_t ret = impl->Init(maxStreams, audioRenderInfo); 41049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init SoundPool"); 42049e185fSopenharmony_ci 43049e185fSopenharmony_ci return impl; 44049e185fSopenharmony_ci} 45049e185fSopenharmony_ci 46049e185fSopenharmony_ciSoundPool::SoundPool() 47049e185fSopenharmony_ci{ 48049e185fSopenharmony_ci MEDIA_LOGI("Construction SoundPool."); 49049e185fSopenharmony_ci} 50049e185fSopenharmony_ci 51049e185fSopenharmony_ciSoundPool::~SoundPool() 52049e185fSopenharmony_ci{ 53049e185fSopenharmony_ci MEDIA_LOGI("Destruction SoundPool."); 54049e185fSopenharmony_ci ReleaseInner(); 55049e185fSopenharmony_ci} 56049e185fSopenharmony_ci 57049e185fSopenharmony_ciint32_t SoundPool::Init(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo) 58049e185fSopenharmony_ci{ 59049e185fSopenharmony_ci // start contruct stream manager 60049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 61049e185fSopenharmony_ci streamIdManager_ = std::make_shared<StreamIDManager>(maxStreams, audioRenderInfo); 62049e185fSopenharmony_ci soundIDManager_ = std::make_shared<SoundIDManager>(); 63049e185fSopenharmony_ci return MSERR_OK; 64049e185fSopenharmony_ci} 65049e185fSopenharmony_ci 66049e185fSopenharmony_cibool SoundPool::CheckInitParam(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo) 67049e185fSopenharmony_ci{ 68049e185fSopenharmony_ci if (maxStreams <= 0) { 69049e185fSopenharmony_ci return false; 70049e185fSopenharmony_ci } 71049e185fSopenharmony_ci if (audioRenderInfo.contentType < AudioStandard::CONTENT_TYPE_UNKNOWN 72049e185fSopenharmony_ci || audioRenderInfo.contentType > AudioStandard::CONTENT_TYPE_ULTRASONIC 73049e185fSopenharmony_ci || audioRenderInfo.streamUsage < AudioStandard::STREAM_USAGE_UNKNOWN 74049e185fSopenharmony_ci || audioRenderInfo.streamUsage > AudioStandard::STREAM_USAGE_VOICE_MODEM_COMMUNICATION 75049e185fSopenharmony_ci || audioRenderInfo.rendererFlags < 0 || audioRenderInfo.rendererFlags > 1) { 76049e185fSopenharmony_ci return false; 77049e185fSopenharmony_ci } 78049e185fSopenharmony_ci return true; 79049e185fSopenharmony_ci} 80049e185fSopenharmony_ci 81049e185fSopenharmony_ciint32_t SoundPool::Load(const std::string url) 82049e185fSopenharmony_ci{ 83049e185fSopenharmony_ci MediaTrace trace("SoundPool::Load url"); 84049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 85049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Load url::%{public}s", url.c_str()); 86049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(!url.empty(), -1, "Failed to obtain SoundPool for load"); 87049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released."); 88049e185fSopenharmony_ci return soundIDManager_->Load(url); 89049e185fSopenharmony_ci} 90049e185fSopenharmony_ci 91049e185fSopenharmony_ciint32_t SoundPool::Load(int32_t fd, int64_t offset, int64_t length) 92049e185fSopenharmony_ci{ 93049e185fSopenharmony_ci MediaTrace trace("SoundPool::Load fd"); 94049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 95049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Load fd::%{public}d, offset::%{public}s, length::%{public}s", fd, 96049e185fSopenharmony_ci std::to_string(offset).c_str(), std::to_string(length).c_str()); 97049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG((fd > 0 && length > 0 && offset >= 0), -1, "Invalid fd param."); 98049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released."); 99049e185fSopenharmony_ci return soundIDManager_->Load(fd, offset, length); 100049e185fSopenharmony_ci} 101049e185fSopenharmony_ci 102049e185fSopenharmony_ciint32_t SoundPool::Play(int32_t soundID, PlayParams playParameters) 103049e185fSopenharmony_ci{ 104049e185fSopenharmony_ci MediaTrace trace("SoundPool::Play"); 105049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 106049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Play soundID::%{public}d ,priority::%{public}d", soundID, playParameters.priority); 107049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, -1, "sound pool have released."); 108049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released."); 109049e185fSopenharmony_ci std::shared_ptr<SoundParser> soundParser = soundIDManager_->FindSoundParser(soundID); 110049e185fSopenharmony_ci 111049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid sound."); 112049e185fSopenharmony_ci if (!soundParser->IsSoundParserCompleted()) { 113049e185fSopenharmony_ci MEDIA_LOGE("sound load no completed. "); 114049e185fSopenharmony_ci return -1; 115049e185fSopenharmony_ci } 116049e185fSopenharmony_ci const int32_t streamID = streamIdManager_->Play(soundParser, playParameters); 117049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Play streamID::%{public}d", streamID); 118049e185fSopenharmony_ci return streamID; 119049e185fSopenharmony_ci} 120049e185fSopenharmony_ci 121049e185fSopenharmony_ciint32_t SoundPool::Stop(int32_t streamID) 122049e185fSopenharmony_ci{ 123049e185fSopenharmony_ci MediaTrace trace("SoundPool::Stop"); 124049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 125049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Stop streamID::%{public}d", streamID); 126049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released."); 127049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 128049e185fSopenharmony_ci return cacheBuffer->Stop(streamID); 129049e185fSopenharmony_ci } 130049e185fSopenharmony_ci return MSERR_INVALID_OPERATION; 131049e185fSopenharmony_ci} 132049e185fSopenharmony_ci 133049e185fSopenharmony_ciint32_t SoundPool::SetLoop(int32_t streamID, int32_t loop) 134049e185fSopenharmony_ci{ 135049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 136049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetLoop streamID:%{public}d, loop:%{public}d", streamID, loop); 137049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released."); 138049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 139049e185fSopenharmony_ci return cacheBuffer->SetLoop(streamID, loop); 140049e185fSopenharmony_ci } 141049e185fSopenharmony_ci return MSERR_INVALID_OPERATION; 142049e185fSopenharmony_ci} 143049e185fSopenharmony_ci 144049e185fSopenharmony_ciint32_t SoundPool::SetPriority(int32_t streamID, int32_t priority) 145049e185fSopenharmony_ci{ 146049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 147049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetPriority streamID::%{public}d ,priority::%{public}d", streamID, priority); 148049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released."); 149049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 150049e185fSopenharmony_ci if (priority < MIN_STREAM_PRIORITY) { 151049e185fSopenharmony_ci MEDIA_LOGI("Invalid priority, align priority to min."); 152049e185fSopenharmony_ci priority = MIN_STREAM_PRIORITY; 153049e185fSopenharmony_ci } 154049e185fSopenharmony_ci int32_t ret = cacheBuffer->SetPriority(streamID, priority); 155049e185fSopenharmony_ci streamIdManager_->ReorderStream(streamID, priority); 156049e185fSopenharmony_ci return ret; 157049e185fSopenharmony_ci } 158049e185fSopenharmony_ci return MSERR_INVALID_OPERATION; 159049e185fSopenharmony_ci} 160049e185fSopenharmony_ci 161049e185fSopenharmony_ciint32_t SoundPool::SetRate(int32_t streamID, AudioStandard::AudioRendererRate renderRate) 162049e185fSopenharmony_ci{ 163049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 164049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetRate streamID:%{public}d, renderRate:%{public}d", streamID, renderRate); 165049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released."); 166049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 167049e185fSopenharmony_ci return cacheBuffer->SetRate(streamID, renderRate); 168049e185fSopenharmony_ci } 169049e185fSopenharmony_ci return MSERR_INVALID_OPERATION; 170049e185fSopenharmony_ci} 171049e185fSopenharmony_ci 172049e185fSopenharmony_ciint32_t SoundPool::SetVolume(int32_t streamID, float leftVolume, float rightVolume) 173049e185fSopenharmony_ci{ 174049e185fSopenharmony_ci if (!CheckVolumeVaild(&leftVolume, &rightVolume)) { 175049e185fSopenharmony_ci return MSERR_INVALID_VAL; 176049e185fSopenharmony_ci } 177049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetVolume streamID:%{public}d, leftVolume:%{public}f, rightVolume:%{public}f", 178049e185fSopenharmony_ci streamID, leftVolume, rightVolume); 179049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released."); 180049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 181049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 182049e185fSopenharmony_ci return cacheBuffer->SetVolume(streamID, leftVolume, rightVolume); 183049e185fSopenharmony_ci } 184049e185fSopenharmony_ci return MSERR_INVALID_OPERATION; 185049e185fSopenharmony_ci} 186049e185fSopenharmony_ci 187049e185fSopenharmony_ciint32_t SoundPool::Unload(int32_t soundID) 188049e185fSopenharmony_ci{ 189049e185fSopenharmony_ci MediaTrace trace("SoundPool::Unload"); 190049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 191049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Unload soundID::%{public}d", soundID); 192049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, -1, "sound pool have released."); 193049e185fSopenharmony_ci CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released."); 194049e185fSopenharmony_ci int32_t streamID = streamIdManager_->GetStreamIDBySoundID(soundID); 195049e185fSopenharmony_ci if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) { 196049e185fSopenharmony_ci cacheBuffer->Stop(streamID); 197049e185fSopenharmony_ci cacheBuffer->Release(); 198049e185fSopenharmony_ci streamIdManager_->ClearStreamIDInDeque(streamID); 199049e185fSopenharmony_ci } 200049e185fSopenharmony_ci return soundIDManager_->Unload(soundID); 201049e185fSopenharmony_ci} 202049e185fSopenharmony_ci 203049e185fSopenharmony_ciint32_t SoundPool::Release() 204049e185fSopenharmony_ci{ 205049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::Release"); 206049e185fSopenharmony_ci return ReleaseInner(); 207049e185fSopenharmony_ci} 208049e185fSopenharmony_ci 209049e185fSopenharmony_ciint32_t SoundPool::ReleaseInner() 210049e185fSopenharmony_ci{ 211049e185fSopenharmony_ci MediaTrace trace("SoundPool::ReleaseInner"); 212049e185fSopenharmony_ci std::lock_guard lock(soundPoolLock_); 213049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::ReleaseInner"); 214049e185fSopenharmony_ci if (streamIdManager_ != nullptr) { 215049e185fSopenharmony_ci streamIdManager_.reset(); 216049e185fSopenharmony_ci } 217049e185fSopenharmony_ci if (soundIDManager_ != nullptr) { 218049e185fSopenharmony_ci soundIDManager_.reset(); 219049e185fSopenharmony_ci } 220049e185fSopenharmony_ci if (callback_ != nullptr) { 221049e185fSopenharmony_ci callback_.reset(); 222049e185fSopenharmony_ci } 223049e185fSopenharmony_ci if (frameWriteCallback_ != nullptr) { 224049e185fSopenharmony_ci frameWriteCallback_.reset(); 225049e185fSopenharmony_ci } 226049e185fSopenharmony_ci SoundPoolManager::GetInstance().Release(getpid()); 227049e185fSopenharmony_ci return MSERR_OK; 228049e185fSopenharmony_ci} 229049e185fSopenharmony_ci 230049e185fSopenharmony_ciint32_t SoundPool::SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> &soundPoolCallback) 231049e185fSopenharmony_ci{ 232049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetSoundPoolCallback"); 233049e185fSopenharmony_ci if (soundIDManager_ != nullptr) soundIDManager_->SetCallback(soundPoolCallback); 234049e185fSopenharmony_ci if (streamIdManager_ != nullptr) streamIdManager_->SetCallback(soundPoolCallback); 235049e185fSopenharmony_ci callback_ = soundPoolCallback; 236049e185fSopenharmony_ci return MSERR_OK; 237049e185fSopenharmony_ci} 238049e185fSopenharmony_ci 239049e185fSopenharmony_ciint32_t SoundPool::SetSoundPoolFrameWriteCallback( 240049e185fSopenharmony_ci const std::shared_ptr<ISoundPoolFrameWriteCallback> &frameWriteCallback) 241049e185fSopenharmony_ci{ 242049e185fSopenharmony_ci MEDIA_LOGI("SoundPool::SetSoundPoolFrameWriteCallback"); 243049e185fSopenharmony_ci if (streamIdManager_ != nullptr) streamIdManager_->SetFrameWriteCallback(frameWriteCallback); 244049e185fSopenharmony_ci frameWriteCallback_ = frameWriteCallback; 245049e185fSopenharmony_ci return MSERR_OK; 246049e185fSopenharmony_ci} 247049e185fSopenharmony_ci 248049e185fSopenharmony_cibool SoundPool::CheckVolumeVaild(float *leftVol, float *rightVol) 249049e185fSopenharmony_ci{ 250049e185fSopenharmony_ci if (*leftVol != std::clamp(*leftVol, 0.f, 1.f) || 251049e185fSopenharmony_ci *rightVol != std::clamp(*rightVol, 0.f, 1.f)) { 252049e185fSopenharmony_ci MEDIA_LOGI("volume l=%{public}f r=%{public}f out of (0.f, 1.f) bounds, using 1.f", *leftVol, *rightVol); 253049e185fSopenharmony_ci *leftVol = *rightVol = 1.f; 254049e185fSopenharmony_ci } 255049e185fSopenharmony_ci if (*leftVol != *rightVol) { 256049e185fSopenharmony_ci MEDIA_LOGI("left volume %{public}f set not eq the right volume %{public}f ,use the left volume", 257049e185fSopenharmony_ci *leftVol, *rightVol); 258049e185fSopenharmony_ci *rightVol = *leftVol; 259049e185fSopenharmony_ci } 260049e185fSopenharmony_ci return true; 261049e185fSopenharmony_ci} 262049e185fSopenharmony_ci} // namespace Media 263049e185fSopenharmony_ci} // namespace OHOS 264