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 #include <unistd.h>
16 #include "media_errors.h"
17 #include "media_log.h"
18 #include "soundpool_manager.h"
19 #include "soundpool.h"
20
21 namespace OHOS {
22 namespace Media {
CreateSoundPool(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)23 std::shared_ptr<ISoundPool> SoundPoolFactory::CreateSoundPool(int maxStreams,
24 AudioStandard::AudioRendererInfo audioRenderInfo)
25 {
26 std::shared_ptr<SoundPool> impl;
27 if (!SoundPool::CheckInitParam(maxStreams, audioRenderInfo)) {
28 return nullptr;
29 }
30 SoundPoolManager::GetInstance().SetSoundPool(getpid(), impl);
31 SoundPoolManager::GetInstance().GetSoundPool(getpid(), impl);
32 CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to get SoundPool");
33
34 int32_t ret = impl->Init(maxStreams, audioRenderInfo);
35 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init SoundPool");
36
37 return impl;
38 }
39
SoundPool()40 SoundPool::SoundPool()
41 {
42 MEDIA_LOGI("Construction SoundPool.");
43 }
44
~SoundPool()45 SoundPool::~SoundPool()
46 {
47 MEDIA_LOGI("Destruction SoundPool.");
48 ReleaseInner();
49 }
50
Init(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)51 int32_t SoundPool::Init(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
52 {
53 // start contruct stream manager
54 std::lock_guard lock(soundPoolLock_);
55 streamIdManager_ = std::make_shared<StreamIDManager>(maxStreams, audioRenderInfo);
56 soundIDManager_ = std::make_shared<SoundIDManager>();
57 return MSERR_OK;
58 }
59
CheckInitParam(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)60 bool SoundPool::CheckInitParam(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
61 {
62 if (maxStreams <= 0) {
63 return false;
64 }
65 if (audioRenderInfo.contentType < AudioStandard::CONTENT_TYPE_UNKNOWN
66 || audioRenderInfo.contentType > AudioStandard::CONTENT_TYPE_ULTRASONIC
67 || audioRenderInfo.streamUsage < AudioStandard::STREAM_USAGE_UNKNOWN
68 || audioRenderInfo.streamUsage > AudioStandard::STREAM_USAGE_VOICE_MODEM_COMMUNICATION
69 || audioRenderInfo.rendererFlags < 0 || audioRenderInfo.rendererFlags > 1) {
70 return false;
71 }
72 return true;
73 }
74
Load(const std::string url)75 int32_t SoundPool::Load(const std::string url)
76 {
77 std::lock_guard lock(soundPoolLock_);
78 CHECK_AND_RETURN_RET_LOG(!url.empty(), -1, "Failed to obtain SoundPool for load");
79 CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
80 return soundIDManager_->Load(url);
81 }
82
Load(int32_t fd,int64_t offset,int64_t length)83 int32_t SoundPool::Load(int32_t fd, int64_t offset, int64_t length)
84 {
85 std::lock_guard lock(soundPoolLock_);
86 CHECK_AND_RETURN_RET_LOG((fd > 0 && length > 0 && offset >= 0), -1, "Invalid fd param.");
87 CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
88 return soundIDManager_->Load(fd, offset, length);
89 }
90
Play(int32_t soundID,PlayParams playParameters)91 int32_t SoundPool::Play(int32_t soundID, PlayParams playParameters)
92 {
93 std::lock_guard lock(soundPoolLock_);
94 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, -1, "sound pool have released.");
95 CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
96 std::shared_ptr<SoundParser> soundParser = soundIDManager_->FindSoundParser(soundID);
97
98 CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid sound.");
99 if (!soundParser->IsSoundParserCompleted()) {
100 MEDIA_LOGE("sound load no completed. ");
101 return -1;
102 }
103 const int32_t streamID = streamIdManager_->Play(soundParser, playParameters);
104 return streamID;
105 }
106
Stop(int32_t streamID)107 int32_t SoundPool::Stop(int32_t streamID)
108 {
109 std::lock_guard lock(soundPoolLock_);
110 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
111 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
112 return cacheBuffer->Stop(streamID);
113 }
114 return MSERR_INVALID_OPERATION;
115 }
116
SetLoop(int32_t streamID,int32_t loop)117 int32_t SoundPool::SetLoop(int32_t streamID, int32_t loop)
118 {
119 std::lock_guard lock(soundPoolLock_);
120 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
121 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
122 return cacheBuffer->SetLoop(streamID, loop);
123 }
124 return MSERR_INVALID_OPERATION;
125 }
126
SetPriority(int32_t streamID,int32_t priority)127 int32_t SoundPool::SetPriority(int32_t streamID, int32_t priority)
128 {
129 std::lock_guard lock(soundPoolLock_);
130 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
131 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
132 if (priority < MIN_STREAM_PRIORITY) {
133 MEDIA_LOGI("Invalid priority, align priority to min.");
134 priority = MIN_STREAM_PRIORITY;
135 }
136 return cacheBuffer->SetPriority(streamID, priority);
137 }
138 return MSERR_INVALID_OPERATION;
139 }
140
SetRate(int32_t streamID,AudioStandard::AudioRendererRate renderRate)141 int32_t SoundPool::SetRate(int32_t streamID, AudioStandard::AudioRendererRate renderRate)
142 {
143 std::lock_guard lock(soundPoolLock_);
144 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
145 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
146 return cacheBuffer->SetRate(streamID, renderRate);
147 }
148 return MSERR_INVALID_OPERATION;
149 }
150
SetVolume(int32_t streamID,float leftVolume,float rightVolume)151 int32_t SoundPool::SetVolume(int32_t streamID, float leftVolume, float rightVolume)
152 {
153 if (!CheckVolumeVaild(&leftVolume, &rightVolume)) {
154 return MSERR_INVALID_VAL;
155 }
156
157 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
158 std::lock_guard lock(soundPoolLock_);
159 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
160 return cacheBuffer->SetVolume(streamID, leftVolume, rightVolume);
161 }
162 return MSERR_INVALID_OPERATION;
163 }
164
Unload(int32_t soundID)165 int32_t SoundPool::Unload(int32_t soundID)
166 {
167 std::lock_guard lock(soundPoolLock_);
168 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, -1, "sound pool have released.");
169 CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
170 if (std::shared_ptr<CacheBuffer> cacheBuffer =
171 streamIdManager_->FindCacheBuffer(streamIdManager_->GetStreamIDBySoundID(soundID))) {
172 cacheBuffer->Release();
173 }
174 return soundIDManager_->Unload(soundID);
175 }
176
Release()177 int32_t SoundPool::Release()
178 {
179 return ReleaseInner();
180 }
181
ReleaseInner()182 int32_t SoundPool::ReleaseInner()
183 {
184 std::lock_guard lock(soundPoolLock_);
185 MEDIA_LOGI("Release SoundPool.");
186 if (streamIdManager_ != nullptr) {
187 streamIdManager_.reset();
188 }
189 if (soundIDManager_ != nullptr) {
190 soundIDManager_.reset();
191 }
192 if (callback_ != nullptr) {
193 callback_.reset();
194 }
195 if (frameWriteCallback_ != nullptr) {
196 frameWriteCallback_.reset();
197 }
198 SoundPoolManager::GetInstance().Release(getpid());
199 return MSERR_OK;
200 }
201
SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> & soundPoolCallback)202 int32_t SoundPool::SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> &soundPoolCallback)
203 {
204 MEDIA_LOGI("SoundPool::%{public}s", __func__);
205 if (soundIDManager_ != nullptr) soundIDManager_->SetCallback(soundPoolCallback);
206 if (streamIdManager_ != nullptr) streamIdManager_->SetCallback(soundPoolCallback);
207 callback_ = soundPoolCallback;
208 return MSERR_OK;
209 }
210
SetSoundPoolFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & frameWriteCallback)211 int32_t SoundPool::SetSoundPoolFrameWriteCallback(
212 const std::shared_ptr<ISoundPoolFrameWriteCallback> &frameWriteCallback)
213 {
214 MEDIA_LOGI("SoundPool::%{public}s", __func__);
215 if (streamIdManager_ != nullptr) streamIdManager_->SetFrameWriteCallback(frameWriteCallback);
216 frameWriteCallback_ = frameWriteCallback;
217 return MSERR_OK;
218 }
219
CheckVolumeVaild(float * leftVol,float * rightVol)220 bool SoundPool::CheckVolumeVaild(float *leftVol, float *rightVol)
221 {
222 if (*leftVol != std::clamp(*leftVol, 0.f, 1.f) ||
223 *rightVol != std::clamp(*rightVol, 0.f, 1.f)) {
224 MEDIA_LOGI("volume l=%{public}f r=%{public}f out of (0.f, 1.f) bounds, using 1.f", *leftVol, *rightVol);
225 *leftVol = *rightVol = 1.f;
226 }
227 if (*leftVol != *rightVol) {
228 MEDIA_LOGI("left volume %{public}f set not eq the right volume %{public}f ,use the left volume",
229 *leftVol, *rightVol);
230 *rightVol = *leftVol;
231 }
232 return true;
233 }
234 } // namespace Media
235 } // namespace OHOS
236