• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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