diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
| commit | d24b8183b93e781080b2c16c487e60d51c12da31 (patch) | |
| tree | fbb89154858984eb8e41556da7e9433040d55cd4 /media/jni | |
| parent | f1e484acb594a726fb57ad0ae4cfe902c7f35858 (diff) | |
| download | frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.zip frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.tar.gz frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.tar.bz2 | |
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'media/jni')
| -rw-r--r-- | media/jni/android_media_MediaRecorder.cpp | 11 | ||||
| -rw-r--r-- | media/jni/soundpool/SoundPool.cpp | 46 | ||||
| -rw-r--r-- | media/jni/soundpool/SoundPool.h | 5 |
3 files changed, 42 insertions, 20 deletions
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 2810a9c..8eb638e 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -60,15 +60,18 @@ static sp<Surface> get_surface(JNIEnv* env, jobject clazz) return sp<Surface>(p); } -static void process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message) +// Returns true if it throws an exception. +static bool process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message) { LOGV("process_media_recorder_call"); if (opStatus == (status_t)INVALID_OPERATION) { jniThrowException(env, "java/lang/IllegalStateException", NULL); + return true; } else if (opStatus != (status_t)OK) { jniThrowException(env, exception, message); + return true; } - return; + return false; } static void android_media_MediaRecorder_setCamera(JNIEnv* env, jobject thiz, jobject camera) @@ -196,7 +199,9 @@ android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz) if (surface != NULL) { const sp<Surface>& native_surface = get_surface(env, surface); LOGI("prepare: surface=%p (id=%d)", native_surface.get(), native_surface->ID()); - process_media_recorder_call(env, mr->setPreviewSurface(native_surface), "java/lang/RuntimeException", "setPreviewSurface failed."); + if (process_media_recorder_call(env, mr->setPreviewSurface(native_surface), "java/lang/RuntimeException", "setPreviewSurface failed.")) { + return; + } } process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed."); } diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 7872a8d..559f9d5 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -64,13 +64,6 @@ SoundPool::SoundPool(jobject soundPoolRef, int maxChannels, int streamType, int mChannels.push_back(&mChannelPool[i]); } - if (AudioSystem::getOutputFrameCount(&mFrameCount) != NO_ERROR) { - mFrameCount = kDefaultFrameCount; - } - if (AudioSystem::getOutputSamplingRate(&mSampleRate) != NO_ERROR) { - mSampleRate = kDefaultSampleRate; - } - // start decode thread startThreads(); } @@ -481,8 +474,8 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV { AudioTrack* oldTrack; - LOGV("play: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", - sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate); + LOGV("play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", + this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate); // if not idle, this voice is being stolen if (mState != IDLE) { @@ -496,9 +489,17 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV } // initialize track + int afFrameCount; + int afSampleRate; + if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { + afFrameCount = kDefaultFrameCount; + } + if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) { + afSampleRate = kDefaultSampleRate; + } int numChannels = sample->numChannels(); uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); - uint32_t bufferFrames = (mSoundPool->mFrameCount * sampleRate) / mSoundPool->mSampleRate; + uint32_t bufferFrames = (afFrameCount * sampleRate) / afSampleRate; uint32_t frameCount = 0; if (loop) { @@ -511,12 +512,21 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV } AudioTrack* newTrack; + + // mToggle toggles each time a track is started on a given channel. + // The toggle is concatenated with the SoundChannel address and passed to AudioTrack + // as callback user data. This enables the detection of callbacks received from the old + // audio track while the new one is being started and avoids processing them with + // wrong audio audio buffer size (mAudioBufferSize) + unsigned long toggle = mToggle ^ 1; + void *userData = (void *)((unsigned long)this | toggle); + #ifdef USE_SHARED_MEM_BUFFER newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(), - numChannels, sample->getIMemory(), 0, callback, this); + numChannels, sample->getIMemory(), 0, callback, userData); #else newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(), - numChannels, frameCount, 0, callback, this, bufferFrames); + numChannels, frameCount, 0, callback, userData, bufferFrames); #endif if (newTrack->initCheck() != NO_ERROR) { LOGE("Error creating AudioTrack"); @@ -529,6 +539,8 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV { Mutex::Autolock lock(&mLock); + // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored. + mToggle = toggle; oldTrack = mAudioTrack; mAudioTrack = newTrack; mPos = 0; @@ -583,7 +595,13 @@ void SoundChannel::nextEvent() void SoundChannel::callback(int event, void* user, void *info) { - SoundChannel* channel = static_cast<SoundChannel*>(user); + unsigned long toggle = (unsigned long)user & 1; + SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); + + if (channel->mToggle != toggle) { + LOGV("callback with wrong toggle"); + return; + } channel->process(event, info); } @@ -592,7 +610,7 @@ void SoundChannel::process(int event, void *info) //LOGV("process(%d)", mChannelID); sp<Sample> sample = mSample; - LOGV("SoundChannel::process event %d", event); +// LOGV("SoundChannel::process event %d", event); if (event == AudioTrack::EVENT_MORE_DATA) { AudioTrack::Buffer* b = static_cast<AudioTrack::Buffer *>(info); diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h index d02ae8b..7802781 100644 --- a/media/jni/soundpool/SoundPool.h +++ b/media/jni/soundpool/SoundPool.h @@ -118,7 +118,7 @@ protected: class SoundChannel : public SoundEvent { public: enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING }; - SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1), mPos(0) {} + SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1), mPos(0), mToggle(0) {} ~SoundChannel(); void init(SoundPool* soundPool); void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume, @@ -151,6 +151,7 @@ private: int mNumChannels; int mPos; int mAudioBufferSize; + unsigned long mToggle; }; // application object for managing a pool of sounds @@ -215,8 +216,6 @@ private: int mAllocated; int mNextSampleID; int mNextChannelID; - int mFrameCount; - int mSampleRate; bool mQuit; }; |
