xref: /aosp_15_r20/frameworks/base/media/jni/soundpool/SoundDecoder.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*d57664e9SAndroid Build Coastguard Worker #define LOG_TAG "SoundPool::SoundDecoder"
19*d57664e9SAndroid Build Coastguard Worker #include "utils/Log.h"
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker #include "SoundDecoder.h"
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker namespace android::soundpool {
24*d57664e9SAndroid Build Coastguard Worker 
25*d57664e9SAndroid Build Coastguard Worker // Maximum Samples that can be background decoded before we block the caller.
26*d57664e9SAndroid Build Coastguard Worker static constexpr size_t kMaxQueueSize = 128;
27*d57664e9SAndroid Build Coastguard Worker 
28*d57664e9SAndroid Build Coastguard Worker // The amount of time we wait for a new Sound decode request
29*d57664e9SAndroid Build Coastguard Worker // before the SoundDecoder thread closes.
30*d57664e9SAndroid Build Coastguard Worker static constexpr int32_t kWaitTimeBeforeCloseMs = 1000;
31*d57664e9SAndroid Build Coastguard Worker 
SoundDecoder(SoundManager * soundManager,size_t threads,int32_t threadPriority)32*d57664e9SAndroid Build Coastguard Worker SoundDecoder::SoundDecoder(SoundManager* soundManager, size_t threads, int32_t threadPriority)
33*d57664e9SAndroid Build Coastguard Worker     : mSoundManager(soundManager)
34*d57664e9SAndroid Build Coastguard Worker {
35*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s(%p, %zu)", __func__, soundManager, threads);
36*d57664e9SAndroid Build Coastguard Worker     // ThreadPool is created, but we don't launch any threads.
37*d57664e9SAndroid Build Coastguard Worker     mThreadPool = std::make_unique<ThreadPool>(
38*d57664e9SAndroid Build Coastguard Worker             std::min(threads, (size_t)std::thread::hardware_concurrency()),
39*d57664e9SAndroid Build Coastguard Worker             "SoundDecoder_",
40*d57664e9SAndroid Build Coastguard Worker             threadPriority);
41*d57664e9SAndroid Build Coastguard Worker }
42*d57664e9SAndroid Build Coastguard Worker 
~SoundDecoder()43*d57664e9SAndroid Build Coastguard Worker SoundDecoder::~SoundDecoder()
44*d57664e9SAndroid Build Coastguard Worker {
45*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
46*d57664e9SAndroid Build Coastguard Worker     quit();
47*d57664e9SAndroid Build Coastguard Worker }
48*d57664e9SAndroid Build Coastguard Worker 
quit()49*d57664e9SAndroid Build Coastguard Worker void SoundDecoder::quit()
50*d57664e9SAndroid Build Coastguard Worker {
51*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
52*d57664e9SAndroid Build Coastguard Worker     {
53*d57664e9SAndroid Build Coastguard Worker         std::lock_guard lock(mLock);
54*d57664e9SAndroid Build Coastguard Worker         mQuit = true;
55*d57664e9SAndroid Build Coastguard Worker         mQueueSpaceAvailable.notify_all(); // notify all load waiters
56*d57664e9SAndroid Build Coastguard Worker         mQueueDataAvailable.notify_all();  // notify all worker threads
57*d57664e9SAndroid Build Coastguard Worker     }
58*d57664e9SAndroid Build Coastguard Worker     mThreadPool->quit();
59*d57664e9SAndroid Build Coastguard Worker }
60*d57664e9SAndroid Build Coastguard Worker 
run(int32_t id)61*d57664e9SAndroid Build Coastguard Worker void SoundDecoder::run(int32_t id)
62*d57664e9SAndroid Build Coastguard Worker {
63*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s(%d): entering", __func__, id);
64*d57664e9SAndroid Build Coastguard Worker     std::unique_lock lock(mLock);
65*d57664e9SAndroid Build Coastguard Worker     while (!mQuit) {
66*d57664e9SAndroid Build Coastguard Worker         if (mSoundIDs.size() == 0) {
67*d57664e9SAndroid Build Coastguard Worker             ALOGV("%s(%d): waiting", __func__, id);
68*d57664e9SAndroid Build Coastguard Worker             mQueueDataAvailable.wait_for(
69*d57664e9SAndroid Build Coastguard Worker                     lock, std::chrono::duration<int32_t, std::milli>(kWaitTimeBeforeCloseMs));
70*d57664e9SAndroid Build Coastguard Worker             if (mSoundIDs.size() == 0) {
71*d57664e9SAndroid Build Coastguard Worker                 break; // no new sound, exit this thread.
72*d57664e9SAndroid Build Coastguard Worker             }
73*d57664e9SAndroid Build Coastguard Worker             continue;
74*d57664e9SAndroid Build Coastguard Worker         }
75*d57664e9SAndroid Build Coastguard Worker         const int32_t soundID = mSoundIDs.front();
76*d57664e9SAndroid Build Coastguard Worker         mSoundIDs.pop_front();
77*d57664e9SAndroid Build Coastguard Worker         mQueueSpaceAvailable.notify_one();
78*d57664e9SAndroid Build Coastguard Worker         ALOGV("%s(%d): processing soundID: %d  size: %zu", __func__, id, soundID, mSoundIDs.size());
79*d57664e9SAndroid Build Coastguard Worker         lock.unlock();
80*d57664e9SAndroid Build Coastguard Worker         std::shared_ptr<Sound> sound = mSoundManager->findSound(soundID);
81*d57664e9SAndroid Build Coastguard Worker         status_t status = NO_INIT;
82*d57664e9SAndroid Build Coastguard Worker         if (sound.get() != nullptr) {
83*d57664e9SAndroid Build Coastguard Worker             status = sound->doLoad();
84*d57664e9SAndroid Build Coastguard Worker         }
85*d57664e9SAndroid Build Coastguard Worker         ALOGV("%s(%d): notifying loaded soundID:%d  status:%d", __func__, id, soundID, status);
86*d57664e9SAndroid Build Coastguard Worker         mSoundManager->notify(SoundPoolEvent(SoundPoolEvent::SOUND_LOADED, soundID, status));
87*d57664e9SAndroid Build Coastguard Worker         lock.lock();
88*d57664e9SAndroid Build Coastguard Worker     }
89*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s(%d): exiting", __func__, id);
90*d57664e9SAndroid Build Coastguard Worker }
91*d57664e9SAndroid Build Coastguard Worker 
loadSound(int32_t soundID)92*d57664e9SAndroid Build Coastguard Worker void SoundDecoder::loadSound(int32_t soundID)
93*d57664e9SAndroid Build Coastguard Worker {
94*d57664e9SAndroid Build Coastguard Worker     ALOGV("%s(%d)", __func__, soundID);
95*d57664e9SAndroid Build Coastguard Worker     size_t pendingSounds;
96*d57664e9SAndroid Build Coastguard Worker     {
97*d57664e9SAndroid Build Coastguard Worker         std::unique_lock lock(mLock);
98*d57664e9SAndroid Build Coastguard Worker         while (mSoundIDs.size() == kMaxQueueSize) {
99*d57664e9SAndroid Build Coastguard Worker             if (mQuit) return;
100*d57664e9SAndroid Build Coastguard Worker             ALOGV("%s: waiting soundID: %d size: %zu", __func__, soundID, mSoundIDs.size());
101*d57664e9SAndroid Build Coastguard Worker             mQueueSpaceAvailable.wait(lock);
102*d57664e9SAndroid Build Coastguard Worker         }
103*d57664e9SAndroid Build Coastguard Worker         if (mQuit) return;
104*d57664e9SAndroid Build Coastguard Worker         mSoundIDs.push_back(soundID);
105*d57664e9SAndroid Build Coastguard Worker         mQueueDataAvailable.notify_one();
106*d57664e9SAndroid Build Coastguard Worker         ALOGV("%s: adding soundID: %d  size: %zu", __func__, soundID, mSoundIDs.size());
107*d57664e9SAndroid Build Coastguard Worker         pendingSounds = mSoundIDs.size();
108*d57664e9SAndroid Build Coastguard Worker     }
109*d57664e9SAndroid Build Coastguard Worker     // Launch threads as needed.  The "as needed" is weakly consistent as we release mLock.
110*d57664e9SAndroid Build Coastguard Worker     if (pendingSounds > mThreadPool->getActiveThreadCount()) {
111*d57664e9SAndroid Build Coastguard Worker         const int32_t id = mThreadPool->launch([this](int32_t id) { run(id); });
112*d57664e9SAndroid Build Coastguard Worker         (void)id; // avoid clang warning -Wunused-variable -Wused-but-marked-unused
113*d57664e9SAndroid Build Coastguard Worker         ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id);
114*d57664e9SAndroid Build Coastguard Worker     }
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker 
117*d57664e9SAndroid Build Coastguard Worker } // end namespace android::soundpool
118