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