• 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     static const int32_t ERROR_RETURN = -1;
28 }
29 
30 namespace OHOS {
31 namespace Media {
CreateSoundPool(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)32 std::shared_ptr<ISoundPool> SoundPoolFactory::CreateSoundPool(int maxStreams,
33     AudioStandard::AudioRendererInfo audioRenderInfo)
34 {
35     MEDIA_LOGI("SoundPoolFactory::CreateSoundPool");
36     std::shared_ptr<SoundPool> impl;
37     if (!SoundPool::CheckInitParam(maxStreams, audioRenderInfo)) {
38         return nullptr;
39     }
40     int32_t apiVersion = GetAPIVersion();
41     CHECK_AND_RETURN_RET_LOG(apiVersion > 0 || apiVersion == FAULT_API_VERSION, nullptr, "invalid apiVersion");
42     if (apiVersion > 0 && apiVersion < SOUNDPOOL_API_VERSION_ISOLATION) {
43         MEDIA_LOGI("SoundPoolFactory::CreateSoundPool go old version");
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 
CreateParallelSoundPool(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)64 std::shared_ptr<ISoundPool> SoundPoolFactory::CreateParallelSoundPool(int maxStreams,
65     AudioStandard::AudioRendererInfo audioRenderInfo)
66 {
67     MEDIA_LOGI("SoundPoolFactory::CreateParallelSoundPool");
68     std::shared_ptr<SoundPool> impl;
69     if (!SoundPool::CheckInitParam(maxStreams, audioRenderInfo)) {
70         return nullptr;
71     }
72     int32_t apiVersion = GetAPIVersion();
73     CHECK_AND_RETURN_RET_LOG(apiVersion > 0 || apiVersion == FAULT_API_VERSION, nullptr, "invalid apiVersion");
74     int32_t ret = SoundPoolManagerMulti::GetInstance().GetSoundPoolInstance(impl);
75     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK && impl != nullptr, nullptr, "failed to get SoundPoolMulti");
76 
77     ret = impl->InitParallel(maxStreams, audioRenderInfo);
78     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init SoundPoolMulti");
79     impl->SetApiVersion(apiVersion);
80 
81     return impl;
82 }
83 
SoundPool()84 SoundPool::SoundPool()
85 {
86     MEDIA_LOGI("Construction SoundPool.");
87 }
88 
~SoundPool()89 SoundPool::~SoundPool()
90 {
91     MEDIA_LOGI("Destruction SoundPool.");
92     ReleaseInner();
93 }
94 
Init(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)95 int32_t SoundPool::Init(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
96 {
97     // start contruct stream manager
98     std::lock_guard lock(soundPoolLock_);
99     streamIdManager_ = std::make_shared<StreamIDManager>(maxStreams, audioRenderInfo);
100     int ret = streamIdManager_->InitThreadPool();
101     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "failed to init streamIdManager");
102     soundIDManager_ = std::make_shared<SoundIDManager>();
103     return MSERR_OK;
104 }
105 
InitParallel(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)106 int32_t SoundPool::InitParallel(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
107 {
108     std::lock_guard lock(soundPoolLock_);
109     soundIDManager_ = std::make_shared<SoundIDManager>();
110     parallelStreamManager_ = std::make_shared<ParallelStreamManager>(maxStreams, audioRenderInfo);
111     int ret = parallelStreamManager_->InitThreadPool();
112     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "failed to init parallelStreamManager");
113     parallelStreamFlag_ = true;
114     return MSERR_OK;
115 }
116 
CheckInitParam(int maxStreams,AudioStandard::AudioRendererInfo audioRenderInfo)117 bool SoundPool::CheckInitParam(int maxStreams, AudioStandard::AudioRendererInfo audioRenderInfo)
118 {
119     if (maxStreams <= 0) {
120         return false;
121     }
122     bool isRendererFlagsInvalid = !CheckRendererFlagsValid(audioRenderInfo);
123     if (audioRenderInfo.contentType < AudioStandard::CONTENT_TYPE_UNKNOWN
124         || audioRenderInfo.contentType > AudioStandard::CONTENT_TYPE_ULTRASONIC
125         || audioRenderInfo.streamUsage < AudioStandard::STREAM_USAGE_UNKNOWN
126         || audioRenderInfo.streamUsage > AudioStandard::STREAM_USAGE_VOICE_MODEM_COMMUNICATION
127         || isRendererFlagsInvalid) {
128         return false;
129     }
130     return true;
131 }
132 
Load(const std::string url)133 int32_t SoundPool::Load(const std::string url)
134 {
135     MediaTrace trace("SoundPool::Load url");
136     std::lock_guard lock(soundPoolLock_);
137     MEDIA_LOGI("SoundPool::Load url::%{public}s", url.c_str());
138     CHECK_AND_RETURN_RET_LOG(!url.empty(), -1, "Failed to obtain SoundPool for load");
139     CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
140     return soundIDManager_->Load(url, apiVersion_);
141 }
142 
Load(int32_t fd,int64_t offset,int64_t length)143 int32_t SoundPool::Load(int32_t fd, int64_t offset, int64_t length)
144 {
145     MediaTrace trace("SoundPool::Load fd");
146     std::lock_guard lock(soundPoolLock_);
147     MEDIA_LOGI("SoundPool::Load fd::%{public}d, offset::%{public}s, length::%{public}s", fd,
148         std::to_string(offset).c_str(), std::to_string(length).c_str());
149     CHECK_AND_RETURN_RET_LOG((fd > 0 && length > 0 && offset >= 0), -1, "Invalid fd param.");
150     CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
151     return soundIDManager_->Load(fd, offset, length, apiVersion_);
152 }
153 
Play(int32_t soundID,PlayParams playParameters)154 int32_t SoundPool::Play(int32_t soundID, PlayParams playParameters)
155 {
156     MediaTrace trace("SoundPool::Play");
157     std::lock_guard lock(soundPoolLock_);
158     MEDIA_LOGI("SoundPool::Play soundID::%{public}d ,priority::%{public}d", soundID, playParameters.priority);
159     CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
160     std::shared_ptr<SoundParser> soundParser = soundIDManager_->FindSoundParser(soundID);
161 
162     CHECK_AND_RETURN_RET_LOG(soundParser != nullptr, -1, "Invalid sound.");
163     if (!soundParser->IsSoundParserCompleted()) {
164         MEDIA_LOGE("sound load no completed. ");
165         return -1;
166     }
167     int32_t streamID;
168     if (parallelStreamFlag_) {
169         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, ERROR_RETURN,
170             "parallelStreamManager_ have released.");
171         streamID = parallelStreamManager_->Play(soundParser, playParameters);
172     } else {
173         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, ERROR_RETURN, "sound pool have released.");
174         streamID = streamIdManager_->Play(soundParser, playParameters);
175     }
176     MEDIA_LOGI("SoundPool::Play streamID::%{public}d", streamID);
177     return streamID;
178 }
179 
Stop(int32_t streamID)180 int32_t SoundPool::Stop(int32_t streamID)
181 {
182     MediaTrace trace("SoundPool::Stop");
183     std::lock_guard lock(soundPoolLock_);
184     MEDIA_LOGI("SoundPool::Stop streamID::%{public}d", streamID);
185     if (parallelStreamFlag_) {
186         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
187             "parallelStreamManager_ have released.");
188         if (std::shared_ptr<Stream> stream = parallelStreamManager_->FindStreamLock(streamID)) {
189             return stream->Stop();
190         }
191     } else {
192         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
193         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
194             return cacheBuffer->Stop(streamID);
195         }
196     }
197     MEDIA_LOGI("SoundPool::Stop can not find stream or cachebuffer streamID::%{public}d", streamID);
198     return MSERR_INVALID_OPERATION;
199 }
200 
SetLoop(int32_t streamID,int32_t loop)201 int32_t SoundPool::SetLoop(int32_t streamID, int32_t loop)
202 {
203     std::lock_guard lock(soundPoolLock_);
204     MEDIA_LOGI("SoundPool::SetLoop streamID:%{public}d, loop:%{public}d", streamID, loop);
205     if (parallelStreamFlag_) {
206         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
207             "parallelStreamManager_ have released.");
208         if (std::shared_ptr<Stream> stream = parallelStreamManager_->FindStreamLock(streamID)) {
209             return stream->SetLoop(loop);
210         }
211     } else {
212         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
213         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
214             return cacheBuffer->SetLoop(streamID, loop);
215         }
216     }
217     MEDIA_LOGI("SoundPool::SetLoop can not find stream or cachebuffer streamID::%{public}d", streamID);
218     return MSERR_INVALID_OPERATION;
219 }
220 
SetPriority(int32_t streamID,int32_t priority)221 int32_t SoundPool::SetPriority(int32_t streamID, int32_t priority)
222 {
223     std::lock_guard lock(soundPoolLock_);
224     MEDIA_LOGI("SoundPool::SetPriority streamID::%{public}d ,priority::%{public}d", streamID, priority);
225     if (priority < MIN_STREAM_PRIORITY) {
226         MEDIA_LOGI("Invalid priority, align priority to min.");
227         priority = MIN_STREAM_PRIORITY;
228     }
229     if (parallelStreamFlag_) {
230         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
231             "parallelStreamManager_ have released.");
232         if (std::shared_ptr<Stream> stream = parallelStreamManager_->FindStreamLock(streamID)) {
233             int32_t ret = stream->SetPriority(priority);
234             parallelStreamManager_->ReorderStream();
235             return ret;
236         }
237     } else {
238         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
239         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
240             int32_t ret = cacheBuffer->SetPriority(streamID, priority);
241             streamIdManager_->ReorderStream(streamID, priority);
242             return ret;
243         }
244     }
245     MEDIA_LOGI("SoundPool::SetPriority can not find stream or cachebuffer streamID::%{public}d", streamID);
246     return MSERR_INVALID_OPERATION;
247 }
248 
SetRate(int32_t streamID,AudioStandard::AudioRendererRate renderRate)249 int32_t SoundPool::SetRate(int32_t streamID, AudioStandard::AudioRendererRate renderRate)
250 {
251     std::lock_guard lock(soundPoolLock_);
252     MEDIA_LOGI("SoundPool::SetRate streamID:%{public}d, renderRate:%{public}d", streamID, renderRate);
253     if (parallelStreamFlag_) {
254         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
255             "parallelStreamManager_ have released.");
256         if (std::shared_ptr<Stream> stream = parallelStreamManager_->FindStreamLock(streamID)) {
257             return stream->SetRate(renderRate);
258         }
259     } else {
260         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
261         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
262             return cacheBuffer->SetRate(streamID, renderRate);
263         }
264     }
265     MEDIA_LOGI("SoundPool::SetRate can not find stream or cachebuffer streamID::%{public}d", streamID);
266     return MSERR_INVALID_OPERATION;
267 }
268 
SetVolume(int32_t streamID,float leftVolume,float rightVolume)269 int32_t SoundPool::SetVolume(int32_t streamID, float leftVolume, float rightVolume)
270 {
271     if (!CheckVolumeVaild(&leftVolume, &rightVolume)) {
272         return MSERR_INVALID_VAL;
273     }
274     MEDIA_LOGI("SoundPool::SetVolume streamID:%{public}d, leftVolume:%{public}f, rightVolume:%{public}f",
275         streamID, leftVolume, rightVolume);
276     std::lock_guard lock(soundPoolLock_);
277     if (parallelStreamFlag_) {
278         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
279             "parallelStreamManager_ have released.");
280         if (std::shared_ptr<Stream> stream = parallelStreamManager_->FindStreamLock(streamID)) {
281             return stream->SetVolume(leftVolume, rightVolume);
282         }
283     } else {
284         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
285         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
286             return cacheBuffer->SetVolume(streamID, leftVolume, rightVolume);
287         }
288     }
289     MEDIA_LOGI("SoundPool::SetVolume can not find stream or cachebuffer streamID::%{public}d", streamID);
290     return MSERR_INVALID_OPERATION;
291 }
292 
Unload(int32_t soundID)293 int32_t SoundPool::Unload(int32_t soundID)
294 {
295     MediaTrace trace("SoundPool::Unload");
296     std::lock_guard lock(soundPoolLock_);
297     MEDIA_LOGI("SoundPool::Unload soundID::%{public}d", soundID);
298     CHECK_AND_RETURN_RET_LOG(soundIDManager_ != nullptr, -1, "sound id manager have released.");
299     if (parallelStreamFlag_) {
300         CHECK_AND_RETURN_RET_LOG(parallelStreamManager_ != nullptr, MSERR_INVALID_VAL,
301             "parallelStreamManager_ have released.");
302         parallelStreamManager_->UnloadStream(soundID);
303     } else {
304         CHECK_AND_RETURN_RET_LOG(streamIdManager_ != nullptr, MSERR_INVALID_VAL, "sound pool have released.");
305         int32_t streamID = streamIdManager_->GetStreamIDBySoundID(soundID);
306         if (std::shared_ptr<CacheBuffer> cacheBuffer = streamIdManager_->FindCacheBufferLock(streamID)) {
307             cacheBuffer->Stop(streamID);
308             cacheBuffer->Release();
309             streamIdManager_->ClearStreamIDInDeque(streamID, soundID);
310         }
311     }
312     return soundIDManager_->Unload(soundID);
313 }
314 
Release()315 int32_t SoundPool::Release()
316 {
317     MEDIA_LOGI("SoundPool::Release");
318     return ReleaseInner();
319 }
320 
ReleaseInner()321 int32_t SoundPool::ReleaseInner()
322 {
323     MediaTrace trace("SoundPool::ReleaseInner");
324     std::lock_guard lock(soundPoolLock_);
325     MEDIA_LOGI("SoundPool::ReleaseInner");
326     if (streamIdManager_ != nullptr) {
327         streamIdManager_.reset();
328     }
329     if (soundIDManager_ != nullptr) {
330         soundIDManager_.reset();
331     }
332     if (parallelStreamManager_ != nullptr) {
333         parallelStreamManager_.reset();
334     }
335     if (callback_ != nullptr) {
336         callback_.reset();
337     }
338     if (frameWriteCallback_ != nullptr) {
339         frameWriteCallback_.reset();
340     }
341 
342     if (apiVersion_ > 0 && apiVersion_ < SOUNDPOOL_API_VERSION_ISOLATION && !parallelStreamFlag_ &&
343         !isReleased_) {
344         SoundPoolManager::GetInstance().Release(getpid());
345         isReleased_ = true;
346         MEDIA_LOGI("SoundPool::ReleaseInner old have released once");
347     } else if (apiVersion_ == FAULT_API_VERSION || apiVersion_ >= SOUNDPOOL_API_VERSION_ISOLATION ||
348         parallelStreamFlag_) {
349         std::shared_ptr<SoundPool> sharedPtr(this, [](SoundPool*) {
350         });
351         SoundPoolManagerMulti::GetInstance().ReleaseInstance(sharedPtr);
352     } else {
353         MEDIA_LOGI("SoundPool::ReleaseInner error apiVersion_: %{public}d", apiVersion_);
354     }
355     return MSERR_OK;
356 }
357 
SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> & soundPoolCallback)358 int32_t SoundPool::SetSoundPoolCallback(const std::shared_ptr<ISoundPoolCallback> &soundPoolCallback)
359 {
360     MEDIA_LOGI("SoundPool::SetSoundPoolCallback");
361     if (soundIDManager_ != nullptr) {
362         soundIDManager_->SetCallback(soundPoolCallback);
363     }
364     if (streamIdManager_ != nullptr) {
365         streamIdManager_->SetCallback(soundPoolCallback);
366     }
367     if (parallelStreamManager_ != nullptr) {
368         parallelStreamManager_->SetCallback(soundPoolCallback);
369     }
370     callback_ = soundPoolCallback;
371     return MSERR_OK;
372 }
373 
SetSoundPoolFrameWriteCallback(const std::shared_ptr<ISoundPoolFrameWriteCallback> & frameWriteCallback)374 int32_t SoundPool::SetSoundPoolFrameWriteCallback(
375     const std::shared_ptr<ISoundPoolFrameWriteCallback> &frameWriteCallback)
376 {
377     MEDIA_LOGI("SoundPool::SetSoundPoolFrameWriteCallback");
378     if (streamIdManager_ != nullptr) {
379         streamIdManager_->SetFrameWriteCallback(frameWriteCallback);
380     }
381     if (parallelStreamManager_ != nullptr) {
382         parallelStreamManager_->SetFrameWriteCallback(frameWriteCallback);
383     }
384     frameWriteCallback_ = frameWriteCallback;
385     return MSERR_OK;
386 }
387 
CheckVolumeVaild(float * leftVol,float * rightVol)388 bool SoundPool::CheckVolumeVaild(float *leftVol, float *rightVol)
389 {
390     if (*leftVol != std::clamp(*leftVol, 0.f, 1.f) ||
391         *rightVol != std::clamp(*rightVol, 0.f, 1.f)) {
392         MEDIA_LOGI("volume l=%{public}f r=%{public}f out of (0.f, 1.f) bounds, using 1.f", *leftVol, *rightVol);
393         *leftVol = *rightVol = 1.f;
394     }
395     if (*leftVol != *rightVol) {
396         MEDIA_LOGI("left volume %{public}f set not eq the right volume %{public}f ,use the left volume",
397             *leftVol, *rightVol);
398         *rightVol = *leftVol;
399     }
400     return true;
401 }
402 
SetApiVersion(int32_t apiVersion)403 void SoundPool::SetApiVersion(int32_t apiVersion)
404 {
405     std::lock_guard lock(soundPoolLock_);
406     apiVersion_ = apiVersion;
407 }
408 
CheckRendererFlagsValid(AudioStandard::AudioRendererInfo audioRenderInfo)409 bool SoundPool::CheckRendererFlagsValid(AudioStandard::AudioRendererInfo audioRenderInfo)
410 {
411     if (audioRenderInfo.rendererFlags == 0 || audioRenderInfo.rendererFlags == 1) {
412         return true;
413     }
414     bool isBundleNameValid = false;
415     std::string bundleName = AudioStandard::AudioSystemManager::GetInstance()->GetSelfBundleName(getuid());
416     AudioStandard::AudioSystemManager::GetInstance()->CheckVKBInfo(bundleName, isBundleNameValid);
417     if (audioRenderInfo.rendererFlags == AudioStandard::AUDIO_FLAG_VKB_NORMAL && isBundleNameValid) {
418         return true;
419     }
420     if (audioRenderInfo.rendererFlags == AudioStandard::AUDIO_FLAG_VKB_FAST && isBundleNameValid) {
421         return true;
422     }
423     return false;
424 }
425 
426 } // namespace Media
427 } // namespace OHOS
428