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