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_INFO_LOG("Construction SoundPool.");
43 }
44
~SoundPool()45 SoundPool::~SoundPool()
46 {
47 MEDIA_INFO_LOG("Destruction SoundPool.");
48 Release();
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 streamIdManager_ = std::make_shared<StreamIDManager>(maxStreams, audioRenderInfo);
55 soundIDManager_ = std::make_shared<SoundIDManager>();
56 return MSERR_OK;
57 }
58
CheckInitParam(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)59 bool SoundPool::CheckInitParam(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
60 {
61 if (maxStreams <= 0) {
62 return false;
63 }
64 if (audioRenderInfo.contentType < AudioStandard::CONTENT_TYPE_UNKNOWN
65 || audioRenderInfo.contentType > AudioStandard::CONTENT_TYPE_ULTRASONIC
66 || audioRenderInfo.streamUsage < AudioStandard::STREAM_USAGE_UNKNOWN
67 || audioRenderInfo.streamUsage > AudioStandard::STREAM_USAGE_VOICE_MODEM_COMMUNICATION
68 || audioRenderInfo.rendererFlags < 0 || audioRenderInfo.rendererFlags > 1) {
69 return false;
70 }
71 return true;
72 }
73
Load(const std::string url)74 int32_t SoundPool::Load(const std::string url)
75 {
76 MEDIA_INFO_LOG("SoundPool::Load url::%{public}s", url.c_str());
77 CHECK_AND_RETURN_RET_LOG(!url.empty(), -1, "Failed to obtain SoundPool for load");
78 std::lock_guard lock(soundPoolLock_);
79 return soundIDManager_->Load(url);
80 }
81
Load(int32_t fd,int64_t offset,int64_t length)82 int32_t SoundPool::Load(int32_t fd, int64_t offset, int64_t length)
83 {
84 MEDIA_INFO_LOG("SoundPool::Load fd::%{public}d", fd);
85 CHECK_AND_RETURN_RET_LOG((fd > 0 && length > 0 && offset >= 0), -1, "Invalid fd param.");
86 std::lock_guard lock(soundPoolLock_);
87 return soundIDManager_->Load(fd, offset, length);
88 }
89
Play(int32_t soundID,PlayParams playParameters)90 int32_t SoundPool::Play(int32_t soundID, PlayParams playParameters)
91 {
92 MEDIA_INFO_LOG("SoundPool::Play soundID::%{public}d ,priority::%{public}d", soundID, playParameters.priority);
93 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, -1, "sound pool have released.");
94 std::lock_guard lock(soundPoolLock_);
95 std::shared_ptr<SoundParser> soundParser = soundIDManager_->FindSoundParser(soundID);
96
97 CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid sound.");
98 if (!soundParser->IsSoundParserCompleted()) {
99 MEDIA_ERR_LOG("sound load no completed. ");
100 return -1;
101 }
102 const int32_t streamID = streamIdManager_->Play(soundParser, playParameters);
103 MEDIA_INFO_LOG("SoundPool::Play streamID::%{public}d", streamID);
104 return streamID;
105 }
106
Stop(int32_t streamID)107 int32_t SoundPool::Stop(int32_t streamID)
108 {
109 MEDIA_INFO_LOG("SoundPool::Stop streamID::%{public}d", streamID);
110 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
111 std::lock_guard lock(soundPoolLock_);
112 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
113 return cacheBuffer->Stop(streamID);
114 }
115 return MSERR_INVALID_OPERATION;
116 }
117
SetLoop(int32_t streamID,int32_t loop)118 int32_t SoundPool::SetLoop(int32_t streamID, int32_t loop)
119 {
120 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
121 std::lock_guard lock(soundPoolLock_);
122 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
123 return cacheBuffer->SetLoop(streamID, loop);
124 }
125 return MSERR_INVALID_OPERATION;
126 }
127
SetPriority(int32_t streamID,int32_t priority)128 int32_t SoundPool::SetPriority(int32_t streamID, int32_t priority)
129 {
130 MEDIA_INFO_LOG("SoundPool::SetPriority streamID::%{public}d ,priority::%{public}d", streamID, priority);
131 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
132 std::lock_guard lock(soundPoolLock_);
133 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
134 if (priority < MIN_STREAM_PRIORITY) {
135 MEDIA_INFO_LOG("Invalid priority, align priority to min.");
136 priority = MIN_STREAM_PRIORITY;
137 }
138 int32_t ret = cacheBuffer->SetPriority(streamID, priority);
139 streamIdManager_->ReorderStream(streamID, priority);
140 return ret;
141 }
142 return MSERR_INVALID_OPERATION;
143 }
144
SetRate(int32_t streamID,AudioStandard::AudioRendererRate renderRate)145 int32_t SoundPool::SetRate(int32_t streamID, AudioStandard::AudioRendererRate renderRate)
146 {
147 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
148 std::lock_guard lock(soundPoolLock_);
149 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
150 return cacheBuffer->SetRate(streamID, renderRate);
151 }
152 return MSERR_INVALID_OPERATION;
153 }
154
SetVolume(int32_t streamID,float leftVolume,float rightVolume)155 int32_t SoundPool::SetVolume(int32_t streamID, float leftVolume, float rightVolume)
156 {
157 if (!CheckVolumeVaild(&leftVolume, &rightVolume)) {
158 return MSERR_INVALID_VAL;
159 }
160
161 CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
162 std::lock_guard lock(soundPoolLock_);
163 if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBuffer(streamID)) {
164 return cacheBuffer->SetVolume(streamID, leftVolume, rightVolume);
165 }
166 return MSERR_INVALID_OPERATION;
167 }
168
Unload(int32_t soundID)169 int32_t SoundPool::Unload(int32_t soundID)
170 {
171 MEDIA_INFO_LOG("SoundPool::Unload soundID::%{public}d", soundID);
172 return soundIDManager_->Unload(soundID);
173 }
174
Release()175 int32_t SoundPool::Release()
176 {
177 MEDIA_INFO_LOG("Release SoundPool.");
178 SoundPoolManager::GetInstance().Release(getpid());
179
180 if (streamIdManager_ != nullptr) {
181 streamIdManager_.reset();
182 }
183 if (soundIDManager_ != nullptr) {
184 soundIDManager_.reset();
185 }
186 if (callback_ != nullptr) {
187 callback_.reset();
188 }
189 return MSERR_OK;
190 }
191
SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> & soundPoolCallback)192 int32_t SoundPool::SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> &soundPoolCallback)
193 {
194 MEDIA_INFO_LOG("SoundPool::%{public}s", __func__);
195 if (soundIDManager_ != nullptr) soundIDManager_->SetCallback(soundPoolCallback);
196 if (streamIdManager_ != nullptr) streamIdManager_->SetCallback(soundPoolCallback);
197 callback_ = soundPoolCallback;
198 return MSERR_OK;
199 }
200
CheckVolumeVaild(float * leftVol,float * rightVol)201 bool SoundPool::CheckVolumeVaild(float *leftVol, float *rightVol)
202 {
203 if (*leftVol != std::clamp(*leftVol, 0.f, 1.f) ||
204 *rightVol != std::clamp(*rightVol, 0.f, 1.f)) {
205 MEDIA_INFO_LOG("volume l=%{public}f r=%{public}f out of (0.f, 1.f) bounds, using 1.f", *leftVol, *rightVol);
206 *leftVol = *rightVol = 1.f;
207 }
208 if (*leftVol != *rightVol) {
209 MEDIA_INFO_LOG("left volume %{public}f set not eq the right volume %{public}f ,use the left volume",
210 *leftVol, *rightVol);
211 *rightVol = *leftVol;
212 }
213 return true;
214 }
215 } // namespace Media
216 } // namespace OHOS
217