From 3b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 14 Nov 2012 08:44:39 -0800 Subject: Use uint32_t for sample rate Change-Id: Ie240b48fb54b08359f69ecd4e5f8bda3d15cbe80 --- media/libmedia/SoundPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index abc8899..b321e92 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -569,7 +569,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV // initialize track int afFrameCount; - int afSampleRate; + uint32_t afSampleRate; audio_stream_type_t streamType = mSoundPool->streamType(); if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { afFrameCount = kDefaultFrameCount; -- cgit v1.1 From e33054eb968cbf8ccaee1b0ff0301403902deed6 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 14 Nov 2012 12:54:39 -0800 Subject: Use size_t for frame counts Also fix typo: bufferCount should be frameCount. Change-Id: Ibed539504db75ef99dc21c8ff1bf2987122063a5 --- media/libmedia/SoundPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index b321e92..204e0ce 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -568,7 +568,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV } // initialize track - int afFrameCount; + size_t afFrameCount; uint32_t afSampleRate; audio_stream_type_t streamType = mSoundPool->streamType(); if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { -- cgit v1.1 From a6b47a17fb1288936b491f30cd751172a572df5c Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Mon, 19 Nov 2012 09:49:18 -0800 Subject: delete -> free Strings duplicated with strdup() should be free()d, not deleted. Change-Id: I42bb3df9625bb8d35f80b02d15364b94c36496f8 --- media/libmedia/SoundPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 204e0ce..ee70ef7 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -489,7 +489,7 @@ Sample::~Sample() ::close(mFd); } mData.clear(); - delete mUrl; + free(mUrl); } status_t Sample::doLoad() -- cgit v1.1 From 2799d743ee2ae5a25fe869a7f9c052acc029559f Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 30 May 2013 14:33:29 -0700 Subject: Use sp instead of raw AudioTrack * This change prepares for the new implementation of AudioTrack client, which will require clients to use only sp, not raw AudioTrack *. A raw delete will cause a race condition during AudioTrack destruction. AudioTrack was made a RefBase by commit b68a91a70bc8d0d18e7404e14443d4e4020b3635 on 2011/11/15, when it was needed by OpenSL ES (for the callback protector). At that time, the only other client that was also converted from AudioTrack * to sp was android.media.AudioTrack JNI in project frameworks/base (file android_media_AudioTrack.cpp). Details: * Use .clear() instead of delete followed by = NULL. * ALOG %p need .get(). * sp<> don't need to be listed in constructor initializer, if initially 0. * Use == 0 for sp<> vs == NULL for raw pointers. * Use if (sp != 0) instead of if (raw). Change-Id: Ic7cad25795d6e862e112abdc227b6d33afdfce17 --- media/libmedia/SoundPool.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index ee70ef7..e1e88ec 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -547,8 +547,8 @@ void SoundChannel::init(SoundPool* soundPool) void SoundChannel::play(const sp& sample, int nextChannelID, float leftVolume, float rightVolume, int priority, int loop, float rate) { - AudioTrack* oldTrack; - AudioTrack* newTrack; + sp oldTrack; + sp newTrack; status_t status; { // scope for the lock @@ -620,7 +620,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV ALOGE("Error creating AudioTrack"); goto exit; } - ALOGV("setVolume %p", newTrack); + ALOGV("setVolume %p", newTrack.get()); newTrack->setVolume(leftVolume, rightVolume); newTrack->setLoop(0, frameCount, loop); @@ -643,11 +643,9 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV } exit: - ALOGV("delete oldTrack %p", oldTrack); - delete oldTrack; + ALOGV("delete oldTrack %p", oldTrack.get()); if (status != NO_ERROR) { - delete newTrack; - mAudioTrack = NULL; + mAudioTrack.clear(); } } @@ -884,7 +882,7 @@ SoundChannel::~SoundChannel() } // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack // callback thread to exit which may need to execute process() and acquire the mLock. - delete mAudioTrack; + mAudioTrack.clear(); } void SoundChannel::dump() -- cgit v1.1 From 1ab85ec401801ef9a9184650d0f5a1639b45eeb9 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 31 May 2013 09:18:43 -0700 Subject: Include what is needed Remove old includes. Header files only include other header files that they directly need themselves. Change-Id: Ic471386808d9f42ea19ccbd59cb50a5f83a89dd0 --- media/libmedia/SoundPool.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index e1e88ec..7f10e05 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -20,14 +20,8 @@ //#define USE_SHARED_MEM_BUFFER -// XXX needed for timing latency -#include - #include #include - -#include - #include #include "SoundPoolThread.h" -- cgit v1.1 From 8973c0439984f85870dffa7a100580271933c964 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 11 Sep 2013 14:35:16 -0700 Subject: Fix SoundPool.play() looping This is done by configuring SoundPool for shared memory and fast track. Previously SoundPool used a streaming track, and looping in streaming mode relied on the ability to loop the most recently enqueued data. That 'feature' was lost in the new implementation of streaming, so we're now switching from streaming mode to shared memory mode. Shared memory mode had always been desired, but was blocked by bug 2801375 which is fixed now. Bug: 10171337 Change-Id: I2a938e3ffafa2a74d5210b4198b50db20ad5da0e --- media/libmedia/SoundPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 7f10e05..0985164 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -18,7 +18,7 @@ #define LOG_TAG "SoundPool" #include -//#define USE_SHARED_MEM_BUFFER +#define USE_SHARED_MEM_BUFFER #include #include @@ -602,7 +602,7 @@ void SoundChannel::play(const sp& sample, int nextChannelID, float leftV // do not create a new audio track if current track is compatible with sample parameters #ifdef USE_SHARED_MEM_BUFFER newTrack = new AudioTrack(streamType, sampleRate, sample->format(), - channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_NONE, callback, userData); + channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); #else newTrack = new AudioTrack(streamType, sampleRate, sample->format(), channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, -- cgit v1.1 From 8d0fda9660aee7059f802f400875247b01226084 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 18 Sep 2013 10:33:39 -0700 Subject: Partial fix for SoundPool not terminating SoundPool was waiting for EVENT_UNDERRUN only to indicate end of clip. In J, AudioTrack delivered both EVENT_UNDERRUN followed by EVENT_BUFFER_END. However, as of K, AudioTrack is only delivering EVENT_BUFFER_END (this lack of EVENT_UNDERRUN is another bug which still needs to be fixed). The workaround is to also respond to EVENT_BUFFER_END in SoundPool. Bug: 10787103 Change-Id: Id68a23bddd6dd9df6c49c55138197260d71ca468 --- media/libmedia/SoundPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 0985164..5239b2f 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -740,8 +740,8 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) b->size = count; //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); } - } else if (event == AudioTrack::EVENT_UNDERRUN) { - ALOGV("process %p channel %d EVENT_UNDERRUN", this, mChannelID); + } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { + ALOGV("process %p channel %d EVENT_UNDERRUN or EVENT_BUFFER_END", this, mChannelID); mSoundPool->addToStopList(this); } else if (event == AudioTrack::EVENT_LOOP_END) { ALOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info); -- cgit v1.1 From 8bbbd7da02fac3de40139af19f7cf7a7cc3cc824 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 18 Sep 2013 14:15:42 -0700 Subject: Workaround slow AudioTrack destruction Bug: 10809586 Change-Id: I5f30d4deb1233e8ade8967568e40684ef680c395 --- media/libmedia/SoundPool.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 5239b2f..37b400c 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -537,6 +537,18 @@ void SoundChannel::init(SoundPool* soundPool) mSoundPool = soundPool; } +// This class is used to destroy a RefBase asynchronously +class AsyncDestructThread : public Thread +{ +public: + AsyncDestructThread(sp refBase) : mRefBase(refBase) { } +protected: + virtual ~AsyncDestructThread() { } +private: + virtual bool threadLoop() { return false; } + const sp mRefBase; +}; + // call with sound pool lock held void SoundChannel::play(const sp& sample, int nextChannelID, float leftVolume, float rightVolume, int priority, int loop, float rate) @@ -641,6 +653,17 @@ exit: if (status != NO_ERROR) { mAudioTrack.clear(); } + // FIXME AudioTrack destruction should not be slow + if (oldTrack != 0) { + // must be a raw reference to avoid a race after run() + AsyncDestructThread *adt = new AsyncDestructThread(oldTrack); + // guaranteed to not run destructor + oldTrack.clear(); + // after the run(), adt thread will hold a strong reference to oldTrack, + // and the only strong reference to itself + adt->run("AsyncDestruct"); + // do not delete adt here: adt thread destroys itself, and oldTrack if needed + } } void SoundChannel::nextEvent() -- cgit v1.1 From e2773bb17bc5d01e05a77b8913539575ebd04500 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Fri, 20 Sep 2013 18:12:06 +0000 Subject: Revert "Workaround slow AudioTrack destruction" This reverts commit 8bbbd7da02fac3de40139af19f7cf7a7cc3cc824. Change-Id: I269a6c445cbce33451b6a9e74223e36e6abbdbe0 --- media/libmedia/SoundPool.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 37b400c..5239b2f 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -537,18 +537,6 @@ void SoundChannel::init(SoundPool* soundPool) mSoundPool = soundPool; } -// This class is used to destroy a RefBase asynchronously -class AsyncDestructThread : public Thread -{ -public: - AsyncDestructThread(sp refBase) : mRefBase(refBase) { } -protected: - virtual ~AsyncDestructThread() { } -private: - virtual bool threadLoop() { return false; } - const sp mRefBase; -}; - // call with sound pool lock held void SoundChannel::play(const sp& sample, int nextChannelID, float leftVolume, float rightVolume, int priority, int loop, float rate) @@ -653,17 +641,6 @@ exit: if (status != NO_ERROR) { mAudioTrack.clear(); } - // FIXME AudioTrack destruction should not be slow - if (oldTrack != 0) { - // must be a raw reference to avoid a race after run() - AsyncDestructThread *adt = new AsyncDestructThread(oldTrack); - // guaranteed to not run destructor - oldTrack.clear(); - // after the run(), adt thread will hold a strong reference to oldTrack, - // and the only strong reference to itself - adt->run("AsyncDestruct"); - // do not delete adt here: adt thread destroys itself, and oldTrack if needed - } } void SoundChannel::nextEvent() -- cgit v1.1 From 3d00aa6de95fb46e36f2bab4e3facdf0b96acf06 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 24 Sep 2013 09:53:27 -0700 Subject: soundpool: allocate shared memory heap by client Current SoundPool implementation allocates the shared memory heap containing decoded PCM samples in mediaserver process. When mediaserver process crashes, the shared memory heaps allocated by AudioCache cannot be mapped anymore in the new instance of mediaserver. This causes a silent failure to end playback of new sounds because AudioFlinger believes the new AudioTracks are opened in streaming mode and not static mode: it sees a NULL shared memory pointer when the track is created. The fix consists in allocating the memory heap in the client process. Thus the heap is not lost when mediaserver restarts. The global memory usage is the same as this is shared memory. Also added a way to detect that a shared memory is passed when the track is created but cannot be mapped on mediaserver side. Also fix a crash in SoundPool when ALOGV is enabled. Bug: 10894793. Change-Id: Ice6c66ec3b2a409d75dc903a508b6c6fbfb2e8a7 --- media/libmedia/SoundPool.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 5239b2f..8434d43 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -32,6 +32,8 @@ int kDefaultBufferCount = 4; uint32_t kMaxSampleRate = 48000; uint32_t kDefaultSampleRate = 44100; uint32_t kDefaultFrameCount = 1200; +size_t kDefaultHeapSize = 1024 * 1024; // 1MB + SoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality) { @@ -464,7 +466,6 @@ Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length) void Sample::init() { - mData = 0; mSize = 0; mRefCount = 0; mSampleID = 0; @@ -482,7 +483,6 @@ Sample::~Sample() ALOGV("close(%d)", mFd); ::close(mFd); } - mData.clear(); free(mUrl); } @@ -491,44 +491,48 @@ status_t Sample::doLoad() uint32_t sampleRate; int numChannels; audio_format_t format; - sp p; + status_t status; + mHeap = new MemoryHeapBase(kDefaultHeapSize); + ALOGV("Start decode"); if (mUrl) { - p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format); + status = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format, mHeap, &mSize); } else { - p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format); + status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format, + mHeap, &mSize); ALOGV("close(%d)", mFd); ::close(mFd); mFd = -1; } - if (p == 0) { + if (status != NO_ERROR) { ALOGE("Unable to load sample: %s", mUrl); - return -1; + goto error; } ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d", - p->pointer(), p->size(), sampleRate, numChannels); + mHeap->getBase(), mSize, sampleRate, numChannels); if (sampleRate > kMaxSampleRate) { ALOGE("Sample rate (%u) out of range", sampleRate); - return - 1; + status = BAD_VALUE; + goto error; } if ((numChannels < 1) || (numChannels > 2)) { ALOGE("Sample channel count (%d) out of range", numChannels); - return - 1; + status = BAD_VALUE; + goto error; } - //_dumpBuffer(p->pointer(), p->size()); - uint8_t* q = static_cast(p->pointer()) + p->size() - 10; - //_dumpBuffer(q, 10, 10, false); - - mData = p; - mSize = p->size(); + mData = new MemoryBase(mHeap, 0, mSize); mSampleRate = sampleRate; mNumChannels = numChannels; mFormat = format; mState = READY; - return 0; + return NO_ERROR; + +error: + mHeap.clear(); + return status; } @@ -744,7 +748,7 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) ALOGV("process %p channel %d EVENT_UNDERRUN or EVENT_BUFFER_END", this, mChannelID); mSoundPool->addToStopList(this); } else if (event == AudioTrack::EVENT_LOOP_END) { - ALOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info); + ALOGV("End loop %p channel %d", this, mChannelID); } } -- cgit v1.1 From b3cb72a17d9a472883e9e2faa18b42eac533fe99 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Sat, 12 Oct 2013 17:05:19 -0700 Subject: SoundPool: handle new audio track event If the AudioTrack is torn down, SoundPool will never receive the buffer end event and the track will stay active for ever. The fix consists in stopping the AudioTrack when a new audiotrack event is received. Bug: 11193583. Change-Id: I9876eb2a8f75c601368f669acd67b0accf6e2736 --- media/libmedia/SoundPool.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'media/libmedia/SoundPool.cpp') diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp index 8434d43..22e9fad 100644 --- a/media/libmedia/SoundPool.cpp +++ b/media/libmedia/SoundPool.cpp @@ -744,11 +744,16 @@ void SoundChannel::process(int event, void *info, unsigned long toggle) b->size = count; //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); } - } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { - ALOGV("process %p channel %d EVENT_UNDERRUN or EVENT_BUFFER_END", this, mChannelID); + } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END || + event == AudioTrack::EVENT_NEW_IAUDIOTRACK) { + ALOGV("process %p channel %d event %s", + this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" : + (event == AudioTrack::EVENT_BUFFER_END) ? "BUFFER_END" : "NEW_IAUDIOTRACK"); mSoundPool->addToStopList(this); } else if (event == AudioTrack::EVENT_LOOP_END) { ALOGV("End loop %p channel %d", this, mChannelID); + } else { + ALOGW("SoundChannel::process unexpected event %d", event); } } -- cgit v1.1