Merge "Make SoundPool use MediaCodec"
This commit is contained in:
@ -543,11 +543,6 @@ public class SoundPool {
|
|||||||
|
|
||||||
public int load(String path, int priority)
|
public int load(String path, int priority)
|
||||||
{
|
{
|
||||||
// pass network streams to player
|
|
||||||
if (path.startsWith("http:"))
|
|
||||||
return _load(path, priority);
|
|
||||||
|
|
||||||
// try local path
|
|
||||||
int id = 0;
|
int id = 0;
|
||||||
try {
|
try {
|
||||||
File f = new File(path);
|
File f = new File(path);
|
||||||
@ -562,6 +557,7 @@ public class SoundPool {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(Context context, int resId, int priority) {
|
public int load(Context context, int resId, int priority) {
|
||||||
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
|
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
|
||||||
int id = 0;
|
int id = 0;
|
||||||
@ -576,6 +572,7 @@ public class SoundPool {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(AssetFileDescriptor afd, int priority) {
|
public int load(AssetFileDescriptor afd, int priority) {
|
||||||
if (afd != null) {
|
if (afd != null) {
|
||||||
long len = afd.getLength();
|
long len = afd.getLength();
|
||||||
@ -588,16 +585,17 @@ public class SoundPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(FileDescriptor fd, long offset, long length, int priority) {
|
public int load(FileDescriptor fd, long offset, long length, int priority) {
|
||||||
return _load(fd, offset, length, priority);
|
return _load(fd, offset, length, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native final int _load(String uri, int priority);
|
|
||||||
|
|
||||||
private native final int _load(FileDescriptor fd, long offset, long length, int priority);
|
private native final int _load(FileDescriptor fd, long offset, long length, int priority);
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final boolean unload(int soundID);
|
public native final boolean unload(int soundID);
|
||||||
|
|
||||||
|
@Override
|
||||||
public final int play(int soundID, float leftVolume, float rightVolume,
|
public final int play(int soundID, float leftVolume, float rightVolume,
|
||||||
int priority, int loop, float rate) {
|
int priority, int loop, float rate) {
|
||||||
if (isRestricted()) {
|
if (isRestricted()) {
|
||||||
@ -620,16 +618,22 @@ public class SoundPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void pause(int streamID);
|
public native final void pause(int streamID);
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void resume(int streamID);
|
public native final void resume(int streamID);
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void autoPause();
|
public native final void autoPause();
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void autoResume();
|
public native final void autoResume();
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void stop(int streamID);
|
public native final void stop(int streamID);
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void setVolume(int streamID, float leftVolume, float rightVolume) {
|
public final void setVolume(int streamID, float leftVolume, float rightVolume) {
|
||||||
if (isRestricted()) {
|
if (isRestricted()) {
|
||||||
return;
|
return;
|
||||||
@ -639,16 +643,21 @@ public class SoundPool {
|
|||||||
|
|
||||||
private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
|
private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setVolume(int streamID, float volume) {
|
public void setVolume(int streamID, float volume) {
|
||||||
setVolume(streamID, volume, volume);
|
setVolume(streamID, volume, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void setPriority(int streamID, int priority);
|
public native final void setPriority(int streamID, int priority);
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void setLoop(int streamID, int loop);
|
public native final void setLoop(int streamID, int loop);
|
||||||
|
|
||||||
|
@Override
|
||||||
public native final void setRate(int streamID, float rate);
|
public native final void setRate(int streamID, float rate);
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
|
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
|
||||||
{
|
{
|
||||||
synchronized(mLock) {
|
synchronized(mLock) {
|
||||||
@ -729,52 +738,69 @@ public class SoundPool {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(Context context, int resId, int priority) {
|
public int load(Context context, int resId, int priority) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(AssetFileDescriptor afd, int priority) {
|
public int load(AssetFileDescriptor afd, int priority) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int load(FileDescriptor fd, long offset, long length, int priority) {
|
public int load(FileDescriptor fd, long offset, long length, int priority) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final boolean unload(int soundID) {
|
public final boolean unload(int soundID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final int play(int soundID, float leftVolume, float rightVolume,
|
public final int play(int soundID, float leftVolume, float rightVolume,
|
||||||
int priority, int loop, float rate) {
|
int priority, int loop, float rate) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void pause(int streamID) { }
|
public final void pause(int streamID) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void resume(int streamID) { }
|
public final void resume(int streamID) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void autoPause() { }
|
public final void autoPause() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void autoResume() { }
|
public final void autoResume() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void stop(int streamID) { }
|
public final void stop(int streamID) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void setVolume(int streamID,
|
public final void setVolume(int streamID,
|
||||||
float leftVolume, float rightVolume) { }
|
float leftVolume, float rightVolume) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setVolume(int streamID, float volume) {
|
public void setVolume(int streamID, float volume) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void setPriority(int streamID, int priority) { }
|
public final void setPriority(int streamID, int priority) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void setLoop(int streamID, int loop) { }
|
public final void setLoop(int streamID, int loop) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void setRate(int streamID, float rate) { }
|
public final void setRate(int streamID, float rate) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
|
public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void release() { }
|
public final void release() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ LOCAL_PATH:= $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
android_media_SoundPool_SoundPoolImpl.cpp
|
android_media_SoundPool_SoundPoolImpl.cpp \
|
||||||
|
SoundPool.cpp \
|
||||||
|
SoundPoolThread.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
liblog \
|
liblog \
|
||||||
@ -10,7 +12,9 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
libutils \
|
libutils \
|
||||||
libandroid_runtime \
|
libandroid_runtime \
|
||||||
libnativehelper \
|
libnativehelper \
|
||||||
libmedia
|
libmedia \
|
||||||
|
libmediandk \
|
||||||
|
libbinder
|
||||||
|
|
||||||
LOCAL_MODULE:= libsoundpool
|
LOCAL_MODULE:= libsoundpool
|
||||||
|
|
||||||
|
1018
media/jni/soundpool/SoundPool.cpp
Normal file
1018
media/jni/soundpool/SoundPool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
232
media/jni/soundpool/SoundPool.h
Normal file
232
media/jni/soundpool/SoundPool.h
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOUNDPOOL_H_
|
||||||
|
#define SOUNDPOOL_H_
|
||||||
|
|
||||||
|
#include <utils/threads.h>
|
||||||
|
#include <utils/List.h>
|
||||||
|
#include <utils/Vector.h>
|
||||||
|
#include <utils/KeyedVector.h>
|
||||||
|
#include <media/AudioTrack.h>
|
||||||
|
#include <binder/MemoryHeapBase.h>
|
||||||
|
#include <binder/MemoryBase.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
static const int IDLE_PRIORITY = -1;
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
class SoundEvent;
|
||||||
|
class SoundPoolThread;
|
||||||
|
class SoundPool;
|
||||||
|
|
||||||
|
// for queued events
|
||||||
|
class SoundPoolEvent {
|
||||||
|
public:
|
||||||
|
SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
|
||||||
|
mMsg(msg), mArg1(arg1), mArg2(arg2) {}
|
||||||
|
int mMsg;
|
||||||
|
int mArg1;
|
||||||
|
int mArg2;
|
||||||
|
enum MessageType { INVALID, SAMPLE_LOADED };
|
||||||
|
};
|
||||||
|
|
||||||
|
// callback function prototype
|
||||||
|
typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
|
||||||
|
|
||||||
|
// tracks samples used by application
|
||||||
|
class Sample : public RefBase {
|
||||||
|
public:
|
||||||
|
enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
|
||||||
|
Sample(int sampleID, int fd, int64_t offset, int64_t length);
|
||||||
|
~Sample();
|
||||||
|
int sampleID() { return mSampleID; }
|
||||||
|
int numChannels() { return mNumChannels; }
|
||||||
|
int sampleRate() { return mSampleRate; }
|
||||||
|
audio_format_t format() { return mFormat; }
|
||||||
|
size_t size() { return mSize; }
|
||||||
|
int state() { return mState; }
|
||||||
|
uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
|
||||||
|
status_t doLoad();
|
||||||
|
void startLoad() { mState = LOADING; }
|
||||||
|
sp<IMemory> getIMemory() { return mData; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
volatile int32_t mRefCount;
|
||||||
|
uint16_t mSampleID;
|
||||||
|
uint16_t mSampleRate;
|
||||||
|
uint8_t mState : 3;
|
||||||
|
uint8_t mNumChannels : 2;
|
||||||
|
audio_format_t mFormat;
|
||||||
|
int mFd;
|
||||||
|
int64_t mOffset;
|
||||||
|
int64_t mLength;
|
||||||
|
sp<IMemory> mData;
|
||||||
|
sp<MemoryHeapBase> mHeap;
|
||||||
|
};
|
||||||
|
|
||||||
|
// stores pending events for stolen channels
|
||||||
|
class SoundEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
|
||||||
|
mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
|
||||||
|
void set(const sp<Sample>& sample, int channelID, float leftVolume,
|
||||||
|
float rightVolume, int priority, int loop, float rate);
|
||||||
|
sp<Sample> sample() { return mSample; }
|
||||||
|
int channelID() { return mChannelID; }
|
||||||
|
float leftVolume() { return mLeftVolume; }
|
||||||
|
float rightVolume() { return mRightVolume; }
|
||||||
|
int priority() { return mPriority; }
|
||||||
|
int loop() { return mLoop; }
|
||||||
|
float rate() { return mRate; }
|
||||||
|
void clear() { mChannelID = 0; mSample.clear(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sp<Sample> mSample;
|
||||||
|
int mChannelID;
|
||||||
|
float mLeftVolume;
|
||||||
|
float mRightVolume;
|
||||||
|
int mPriority;
|
||||||
|
int mLoop;
|
||||||
|
float mRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
// for channels aka AudioTracks
|
||||||
|
class SoundChannel : public SoundEvent {
|
||||||
|
public:
|
||||||
|
enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
|
||||||
|
SoundChannel() : mState(IDLE), mNumChannels(1),
|
||||||
|
mPos(0), mToggle(0), mAutoPaused(false) {}
|
||||||
|
~SoundChannel();
|
||||||
|
void init(SoundPool* soundPool);
|
||||||
|
void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
|
||||||
|
int priority, int loop, float rate);
|
||||||
|
void setVolume_l(float leftVolume, float rightVolume);
|
||||||
|
void setVolume(float leftVolume, float rightVolume);
|
||||||
|
void stop_l();
|
||||||
|
void stop();
|
||||||
|
void pause();
|
||||||
|
void autoPause();
|
||||||
|
void resume();
|
||||||
|
void autoResume();
|
||||||
|
void setRate(float rate);
|
||||||
|
int state() { return mState; }
|
||||||
|
void setPriority(int priority) { mPriority = priority; }
|
||||||
|
void setLoop(int loop);
|
||||||
|
int numChannels() { return mNumChannels; }
|
||||||
|
void clearNextEvent() { mNextEvent.clear(); }
|
||||||
|
void nextEvent();
|
||||||
|
int nextChannelID() { return mNextEvent.channelID(); }
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void callback(int event, void* user, void *info);
|
||||||
|
void process(int event, void *info, unsigned long toggle);
|
||||||
|
bool doStop_l();
|
||||||
|
|
||||||
|
SoundPool* mSoundPool;
|
||||||
|
sp<AudioTrack> mAudioTrack;
|
||||||
|
SoundEvent mNextEvent;
|
||||||
|
Mutex mLock;
|
||||||
|
int mState;
|
||||||
|
int mNumChannels;
|
||||||
|
int mPos;
|
||||||
|
int mAudioBufferSize;
|
||||||
|
unsigned long mToggle;
|
||||||
|
bool mAutoPaused;
|
||||||
|
};
|
||||||
|
|
||||||
|
// application object for managing a pool of sounds
|
||||||
|
class SoundPool {
|
||||||
|
friend class SoundPoolThread;
|
||||||
|
friend class SoundChannel;
|
||||||
|
public:
|
||||||
|
SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
|
||||||
|
~SoundPool();
|
||||||
|
int load(int fd, int64_t offset, int64_t length, int priority);
|
||||||
|
bool unload(int sampleID);
|
||||||
|
int play(int sampleID, float leftVolume, float rightVolume, int priority,
|
||||||
|
int loop, float rate);
|
||||||
|
void pause(int channelID);
|
||||||
|
void autoPause();
|
||||||
|
void resume(int channelID);
|
||||||
|
void autoResume();
|
||||||
|
void stop(int channelID);
|
||||||
|
void setVolume(int channelID, float leftVolume, float rightVolume);
|
||||||
|
void setPriority(int channelID, int priority);
|
||||||
|
void setLoop(int channelID, int loop);
|
||||||
|
void setRate(int channelID, float rate);
|
||||||
|
const audio_attributes_t* attributes() { return &mAttributes; }
|
||||||
|
|
||||||
|
// called from SoundPoolThread
|
||||||
|
void sampleLoaded(int sampleID);
|
||||||
|
|
||||||
|
// called from AudioTrack thread
|
||||||
|
void done_l(SoundChannel* channel);
|
||||||
|
|
||||||
|
// callback function
|
||||||
|
void setCallback(SoundPoolCallback* callback, void* user);
|
||||||
|
void* getUserData() { return mUserData; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SoundPool() {} // no default constructor
|
||||||
|
bool startThreads();
|
||||||
|
void doLoad(sp<Sample>& sample);
|
||||||
|
sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
|
||||||
|
SoundChannel* findChannel (int channelID);
|
||||||
|
SoundChannel* findNextChannel (int channelID);
|
||||||
|
SoundChannel* allocateChannel_l(int priority);
|
||||||
|
void moveToFront_l(SoundChannel* channel);
|
||||||
|
void notify(SoundPoolEvent event);
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
// restart thread
|
||||||
|
void addToRestartList(SoundChannel* channel);
|
||||||
|
void addToStopList(SoundChannel* channel);
|
||||||
|
static int beginThread(void* arg);
|
||||||
|
int run();
|
||||||
|
void quit();
|
||||||
|
|
||||||
|
Mutex mLock;
|
||||||
|
Mutex mRestartLock;
|
||||||
|
Condition mCondition;
|
||||||
|
SoundPoolThread* mDecodeThread;
|
||||||
|
SoundChannel* mChannelPool;
|
||||||
|
List<SoundChannel*> mChannels;
|
||||||
|
List<SoundChannel*> mRestart;
|
||||||
|
List<SoundChannel*> mStop;
|
||||||
|
DefaultKeyedVector< int, sp<Sample> > mSamples;
|
||||||
|
int mMaxChannels;
|
||||||
|
audio_attributes_t mAttributes;
|
||||||
|
int mAllocated;
|
||||||
|
int mNextSampleID;
|
||||||
|
int mNextChannelID;
|
||||||
|
bool mQuit;
|
||||||
|
|
||||||
|
// callback
|
||||||
|
Mutex mCallbackLock;
|
||||||
|
SoundPoolCallback* mCallback;
|
||||||
|
void* mUserData;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace android
|
||||||
|
|
||||||
|
#endif /*SOUNDPOOL_H_*/
|
114
media/jni/soundpool/SoundPoolThread.cpp
Normal file
114
media/jni/soundpool/SoundPoolThread.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "SoundPoolThread"
|
||||||
|
#include "utils/Log.h"
|
||||||
|
|
||||||
|
#include "SoundPoolThread.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
void SoundPoolThread::write(SoundPoolMsg msg) {
|
||||||
|
Mutex::Autolock lock(&mLock);
|
||||||
|
while (mMsgQueue.size() >= maxMessages) {
|
||||||
|
mCondition.wait(mLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if thread is quitting, don't add to queue
|
||||||
|
if (mRunning) {
|
||||||
|
mMsgQueue.push(msg);
|
||||||
|
mCondition.signal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SoundPoolMsg SoundPoolThread::read() {
|
||||||
|
Mutex::Autolock lock(&mLock);
|
||||||
|
while (mMsgQueue.size() == 0) {
|
||||||
|
mCondition.wait(mLock);
|
||||||
|
}
|
||||||
|
SoundPoolMsg msg = mMsgQueue[0];
|
||||||
|
mMsgQueue.removeAt(0);
|
||||||
|
mCondition.signal();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundPoolThread::quit() {
|
||||||
|
Mutex::Autolock lock(&mLock);
|
||||||
|
if (mRunning) {
|
||||||
|
mRunning = false;
|
||||||
|
mMsgQueue.clear();
|
||||||
|
mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
|
||||||
|
mCondition.signal();
|
||||||
|
mCondition.wait(mLock);
|
||||||
|
}
|
||||||
|
ALOGV("return from quit");
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
|
||||||
|
mSoundPool(soundPool)
|
||||||
|
{
|
||||||
|
mMsgQueue.setCapacity(maxMessages);
|
||||||
|
if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
|
||||||
|
mRunning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundPoolThread::~SoundPoolThread()
|
||||||
|
{
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SoundPoolThread::beginThread(void* arg) {
|
||||||
|
ALOGV("beginThread");
|
||||||
|
SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
|
||||||
|
return soundPoolThread->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SoundPoolThread::run() {
|
||||||
|
ALOGV("run");
|
||||||
|
for (;;) {
|
||||||
|
SoundPoolMsg msg = read();
|
||||||
|
ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
|
||||||
|
switch (msg.mMessageType) {
|
||||||
|
case SoundPoolMsg::KILL:
|
||||||
|
ALOGV("goodbye");
|
||||||
|
return NO_ERROR;
|
||||||
|
case SoundPoolMsg::LOAD_SAMPLE:
|
||||||
|
doLoadSample(msg.mData);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGW("run: Unrecognized message %d\n",
|
||||||
|
msg.mMessageType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundPoolThread::loadSample(int sampleID) {
|
||||||
|
write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundPoolThread::doLoadSample(int sampleID) {
|
||||||
|
sp <Sample> sample = mSoundPool->findSample(sampleID);
|
||||||
|
status_t status = -1;
|
||||||
|
if (sample != 0) {
|
||||||
|
status = sample->doLoad();
|
||||||
|
}
|
||||||
|
mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace android
|
66
media/jni/soundpool/SoundPoolThread.h
Normal file
66
media/jni/soundpool/SoundPoolThread.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOUNDPOOLTHREAD_H_
|
||||||
|
#define SOUNDPOOLTHREAD_H_
|
||||||
|
|
||||||
|
#include <utils/threads.h>
|
||||||
|
#include <utils/Vector.h>
|
||||||
|
#include <media/AudioTrack.h>
|
||||||
|
|
||||||
|
#include "SoundPool.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
class SoundPoolMsg {
|
||||||
|
public:
|
||||||
|
enum MessageType { INVALID, KILL, LOAD_SAMPLE };
|
||||||
|
SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
|
||||||
|
SoundPoolMsg(MessageType MessageType, int data) :
|
||||||
|
mMessageType(MessageType), mData(data) {}
|
||||||
|
uint16_t mMessageType;
|
||||||
|
uint16_t mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class handles background requests from the SoundPool
|
||||||
|
*/
|
||||||
|
class SoundPoolThread {
|
||||||
|
public:
|
||||||
|
SoundPoolThread(SoundPool* SoundPool);
|
||||||
|
~SoundPoolThread();
|
||||||
|
void loadSample(int sampleID);
|
||||||
|
void quit();
|
||||||
|
void write(SoundPoolMsg msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t maxMessages = 5;
|
||||||
|
|
||||||
|
static int beginThread(void* arg);
|
||||||
|
int run();
|
||||||
|
void doLoadSample(int sampleID);
|
||||||
|
const SoundPoolMsg read();
|
||||||
|
|
||||||
|
Mutex mLock;
|
||||||
|
Condition mCondition;
|
||||||
|
Vector<SoundPoolMsg> mMsgQueue;
|
||||||
|
SoundPool* mSoundPool;
|
||||||
|
bool mRunning;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace android
|
||||||
|
|
||||||
|
#endif /*SOUNDPOOLTHREAD_H_*/
|
@ -23,7 +23,7 @@
|
|||||||
#include <nativehelper/jni.h>
|
#include <nativehelper/jni.h>
|
||||||
#include <nativehelper/JNIHelp.h>
|
#include <nativehelper/JNIHelp.h>
|
||||||
#include <android_runtime/AndroidRuntime.h>
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
#include <media/SoundPool.h>
|
#include "SoundPool.h"
|
||||||
|
|
||||||
using namespace android;
|
using namespace android;
|
||||||
|
|
||||||
@ -45,20 +45,6 @@ struct audio_attributes_fields_t {
|
|||||||
static audio_attributes_fields_t javaAudioAttrFields;
|
static audio_attributes_fields_t javaAudioAttrFields;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
static jint
|
|
||||||
android_media_SoundPool_SoundPoolImpl_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
|
|
||||||
{
|
|
||||||
ALOGV("android_media_SoundPool_SoundPoolImpl_load_URL");
|
|
||||||
SoundPool *ap = MusterSoundPool(env, thiz);
|
|
||||||
if (path == NULL) {
|
|
||||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const char* s = env->GetStringUTFChars(path, NULL);
|
|
||||||
int id = ap->load(s, priority);
|
|
||||||
env->ReleaseStringUTFChars(path, s);
|
|
||||||
return (jint) id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint
|
static jint
|
||||||
android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
|
android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
|
||||||
@ -248,10 +234,6 @@ android_media_SoundPool_SoundPoolImpl_release(JNIEnv *env, jobject thiz)
|
|||||||
|
|
||||||
// Dalvik VM type signatures
|
// Dalvik VM type signatures
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
{ "_load",
|
|
||||||
"(Ljava/lang/String;I)I",
|
|
||||||
(void *)android_media_SoundPool_SoundPoolImpl_load_URL
|
|
||||||
},
|
|
||||||
{ "_load",
|
{ "_load",
|
||||||
"(Ljava/io/FileDescriptor;JJI)I",
|
"(Ljava/io/FileDescriptor;JJI)I",
|
||||||
(void *)android_media_SoundPool_SoundPoolImpl_load_FD
|
(void *)android_media_SoundPool_SoundPoolImpl_load_FD
|
||||||
|
Reference in New Issue
Block a user