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 | 5e07b5774c8b376776caa4f5b0a193767697e97e (patch) | |
tree | 3260f49c6f0c5b4699ac6b80b4dc505566af17e8 /media/libmedia | |
parent | e5198b620a9a208ec59ea8457282404725f8ff6e (diff) | |
download | frameworks_av-5e07b5774c8b376776caa4f5b0a193767697e97e.zip frameworks_av-5e07b5774c8b376776caa4f5b0a193767697e97e.tar.gz frameworks_av-5e07b5774c8b376776caa4f5b0a193767697e97e.tar.bz2 |
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/Android.mk | 1 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 18 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 55 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 14 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 50 | ||||
-rw-r--r-- | media/libmedia/IAudioFlingerClient.cpp | 81 | ||||
-rw-r--r-- | media/libmedia/JetPlayer.cpp | 70 | ||||
-rw-r--r-- | media/libmedia/ToneGenerator.cpp | 8 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 10 |
9 files changed, 273 insertions, 34 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 2a697b9..8020da2 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ AudioTrack.cpp \ IAudioFlinger.cpp \ + IAudioFlingerClient.cpp \ IAudioTrack.cpp \ IAudioRecord.cpp \ AudioRecord.cpp \ diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 3d39181..a987b92 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,8 +128,22 @@ status_t AudioRecord::set( return BAD_VALUE; } - // TODO: Get input frame count from hardware. - int minFrameCount = 1024*2; + size_t inputBuffSizeInBytes = -1; + if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) + != NO_ERROR) { + LOGE("AudioSystem could not query the input buffer size."); + return NO_INIT; + } + if (inputBuffSizeInBytes == 0) { + LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", + sampleRate, channelCount, format); + return BAD_VALUE; + } + int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); + + // We use 2* size of input buffer for ping pong use of record buffer. + int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; + LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); if (frameCount == 0) { frameCount = minFrameCount; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index a375b55..cf91105 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -15,6 +15,8 @@ */ #define LOG_TAG "AudioSystem" +//#define LOG_NDEBUG 0 + #include <utils/Log.h> #include <utils/IServiceManager.h> #include <media/AudioSystem.h> @@ -26,12 +28,17 @@ namespace android { // client singleton for AudioFlinger binder interface Mutex AudioSystem::gLock; sp<IAudioFlinger> AudioSystem::gAudioFlinger; -sp<AudioSystem::DeathNotifier> AudioSystem::gDeathNotifier; +sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; // Cached values int AudioSystem::gOutSamplingRate = 0; int AudioSystem::gOutFrameCount = 0; uint32_t AudioSystem::gOutLatency = 0; +// Cached values for recording queries +uint32_t AudioSystem::gPrevInSamplingRate = 16000; +int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT; +int AudioSystem::gPrevInChannelCount = 1; +size_t AudioSystem::gInBuffSize = 0; // establish binder interface to AudioFlinger service @@ -48,15 +55,16 @@ const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() LOGW("AudioFlinger not published, waiting..."); usleep(500000); // 0.5 s } while(true); - if (gDeathNotifier == NULL) { - gDeathNotifier = new DeathNotifier(); + if (gAudioFlingerClient == NULL) { + gAudioFlingerClient = new AudioFlingerClient(); } else { if (gAudioErrorCallback) { gAudioErrorCallback(NO_ERROR); } } - binder->linkToDeath(gDeathNotifier); + binder->linkToDeath(gAudioFlingerClient); gAudioFlinger = interface_cast<IAudioFlinger>(binder); + gAudioFlinger->registerClient(gAudioFlingerClient); // Cache frequently accessed parameters gOutFrameCount = (int)gAudioFlinger->frameCount(); gOutSamplingRate = (int)gAudioFlinger->sampleRate(); @@ -250,7 +258,7 @@ status_t AudioSystem::getOutputSamplingRate(int* samplingRate) const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; // gOutSamplingRate is updated by get_audio_flinger() - } + } *samplingRate = gOutSamplingRate; return NO_ERROR; @@ -261,7 +269,7 @@ status_t AudioSystem::getOutputFrameCount(int* frameCount) if (gOutFrameCount == 0) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - // gOutSamplingRate is updated by get_audio_flinger() + // gOutFrameCount is updated by get_audio_flinger() } *frameCount = gOutFrameCount; return NO_ERROR; @@ -279,14 +287,38 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency) return NO_ERROR; } +status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, + size_t* buffSize) +{ + // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values + if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) + || (channelCount != gPrevInChannelCount)) { + // save the request params + gPrevInSamplingRate = sampleRate; + gPrevInFormat = format; + gPrevInChannelCount = channelCount; + + gInBuffSize = 0; + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) { + return PERMISSION_DENIED; + } + gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount); + } + *buffSize = gInBuffSize; + + return NO_ERROR; +} + // --------------------------------------------------------------------------- -void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) { +void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); AudioSystem::gOutSamplingRate = 0; AudioSystem::gOutFrameCount = 0; AudioSystem::gOutLatency = 0; + AudioSystem::gInBuffSize = 0; if (gAudioErrorCallback) { gAudioErrorCallback(DEAD_OBJECT); @@ -294,6 +326,15 @@ void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) { LOGW("AudioFlinger server died!"); } +void AudioSystem::AudioFlingerClient::audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) { + + AudioSystem::gOutFrameCount = frameCount; + AudioSystem::gOutSamplingRate = samplingRate; + AudioSystem::gOutLatency = latency; + + LOGV("AudioFlinger output changed!"); +} + void AudioSystem::setErrorCallback(audio_error_callback cb) { Mutex::Autolock _l(AudioSystem::gLock); gAudioErrorCallback = cb; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index f9f8568..63b2012 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -603,13 +603,17 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (__builtin_expect(result!=NO_ERROR, false)) { cblk->waitTimeMs += WAIT_PERIOD_MS; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - mAudioTrack->start(); // FIXME: Wake up audioflinger - timeout = 1; + // timing out when a loop has been set and we have already written upto loop end + // is a normal condition: no need to wake AudioFlinger up. + if (cblk->user < cblk->loopEnd) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) " + "user=%08x, server=%08x", cblk->user, cblk->server); + mAudioFlinger->wakeUp(); + timeout = 1; + } cblk->waitTimeMs = 0; } - ; + if (--waitCount == 0) { return TIMED_OUT; } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 018ea6c..4215820 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -51,6 +51,9 @@ enum { GET_MIC_MUTE, IS_MUSIC_ACTIVE, SET_PARAMETER, + REGISTER_CLIENT, + GET_INPUTBUFFERSIZE, + WAKE_UP }; class BpAudioFlinger : public BpInterface<IAudioFlinger> @@ -303,6 +306,33 @@ public: remote()->transact(SET_PARAMETER, data, &reply); return reply.readInt32(); } + + virtual void registerClient(const sp<IAudioFlingerClient>& client) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + remote()->transact(REGISTER_CLIENT, data, &reply); + } + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(sampleRate); + data.writeInt32(format); + data.writeInt32(channelCount); + remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); + return reply.readInt32(); + } + + virtual void wakeUp() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(WAKE_UP, data, &reply); + return; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -470,6 +500,26 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( setParameter(key, value) ); return NO_ERROR; } break; + case REGISTER_CLIENT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder()); + registerClient(client); + return NO_ERROR; + } break; + case GET_INPUTBUFFERSIZE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + uint32_t sampleRate = data.readInt32(); + int format = data.readInt32(); + int channelCount = data.readInt32(); + reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); + return NO_ERROR; + } break; + case WAKE_UP: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + wakeUp(); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp new file mode 100644 index 0000000..d956266 --- /dev/null +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 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_TAG "IAudioFlingerClient" +#include <utils/Log.h> + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Parcel.h> + +#include <media/IAudioFlingerClient.h> + +namespace android { + +enum { + AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION +}; + +class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient> +{ +public: + BpAudioFlingerClient(const sp<IBinder>& impl) + : BpInterface<IAudioFlingerClient>(impl) + { + } + + void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); + data.writeInt32(frameCount); + data.writeInt32(samplingRate); + data.writeInt32(latency); + remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioFlingerClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case AUDIO_OUTPUT_CHANGED: { + CHECK_INTERFACE(IAudioFlingerClient, data, reply); + uint32_t frameCount = data.readInt32(); + uint32_t samplingRate = data.readInt32(); + uint32_t latency = data.readInt32(); + audioOutputChanged(frameCount, samplingRate, latency); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index f0edf88..ead24d4 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -214,12 +214,15 @@ int JetPlayer::render() { } p += count * pLibConfig->numChannels; num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); + + // send events that were generated (if any) to the event callback + fireEventsFromJetQueue(); } // update playback state //LOGV("JetPlayer::render(): updating state"); JET_Status(mEasData, &mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); mPaused = mJetStatus.paused; mMutex.unlock(); // UNLOCK ]]]]]]]] ----------------------------------- @@ -261,9 +264,9 @@ threadExit: //------------------------------------------------------------------------------------------------- -// fire up an event if any of the status fields has changed +// fire up an update if any of the status fields has changed // precondition: mMutex locked -void JetPlayer::fireEventOnStatusChange() +void JetPlayer::fireUpdateOnStatusChange() { if( (mJetStatus.currentUserID != mPreviousJetStatus.currentUserID) ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) { @@ -303,9 +306,31 @@ void JetPlayer::fireEventOnStatusChange() //------------------------------------------------------------------------------------------------- -int JetPlayer::openFile(const char* path) +// fire up all the JET events in the JET engine queue (until the queue is empty) +// precondition: mMutex locked +void JetPlayer::fireEventsFromJetQueue() +{ + if(!mEventCallback) { + // no callback, just empty the event queue + while (JET_GetEvent(mEasData, NULL, NULL)) { } + return; + } + + EAS_U32 rawEvent; + while (JET_GetEvent(mEasData, &rawEvent, NULL)) { + mEventCallback( + JetPlayer::JET_EVENT, + rawEvent, + -1, + mJavaJetPlayerRef); + } +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFile(const char* path) { - LOGV("JetPlayer::openFile(): path=%s", path); + LOGV("JetPlayer::loadFromFile(): path=%s", path); Mutex::Autolock lock(mMutex); @@ -326,6 +351,29 @@ int JetPlayer::openFile(const char* path) return( result ); } + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length) +{ + LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length); + + Mutex::Autolock lock(mMutex); + + mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); + mEasJetFileLoc->fd = fd; + mEasJetFileLoc->offset = offset; + mEasJetFileLoc->length = length; + mEasJetFileLoc->path = NULL; + + EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); + if(result != EAS_SUCCESS) + mState = EAS_STATE_ERROR; + else + mState = EAS_STATE_OPEN; + return( result ); +} + + //------------------------------------------------------------------------------------------------- int JetPlayer::closeFile() { @@ -348,7 +396,7 @@ int JetPlayer::play() JET_Status(mEasData, &mJetStatus); this->dumpJetStatus(&mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); // wake up render thread LOGV("JetPlayer::play(): wakeup render thread"); @@ -368,7 +416,7 @@ int JetPlayer::pause() JET_Status(mEasData, &mJetStatus); this->dumpJetStatus(&mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); return result; @@ -408,6 +456,14 @@ int JetPlayer::triggerClip(int clipId) } //------------------------------------------------------------------------------------------------- +int JetPlayer::clearQueue() +{ + LOGV("JetPlayer::clearQueue"); + Mutex::Autolock lock(mMutex); + return JET_Clear_Queue(mEasData); +} + +//------------------------------------------------------------------------------------------------- void JetPlayer::dump() { LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path); diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index 584d135..fa36460 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -97,10 +97,6 @@ ToneGenerator::ToneGenerator(int streamType, float volume) { LOGE("Unable to marshal AudioFlinger"); return; } - if (AudioSystem::getOutputFrameCount(&mBufferSize) != NO_ERROR) { - LOGE("Unable to marshal AudioFlinger"); - return; - } mStreamType = streamType; mVolume = volume; mpAudioTrack = 0; @@ -275,9 +271,9 @@ bool ToneGenerator::initAudioTrack() { mpAudioTrack = 0; } - // Open audio track in mono, PCM 16bit, default sampling rate, 2 buffers of + // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size mpAudioTrack - = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, NUM_PCM_BUFFERS*mBufferSize, 0, audioCallback, this, mBufferSize); + = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0); if (mpAudioTrack == 0) { LOGE("AudioTrack allocation failed"); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index ebdbda8..31ff507 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -172,7 +172,7 @@ status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player) status_t MediaPlayer::setDataSource(const char *url) { LOGV("setDataSource(%s)", url); - status_t err = UNKNOWN_ERROR; + status_t err = BAD_VALUE; if (url != NULL) { const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { @@ -199,7 +199,7 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) { LOGV("setVideoSurface"); Mutex::Autolock _l(mLock); - if (mPlayer == 0) return UNKNOWN_ERROR; + if (mPlayer == 0) return NO_INIT; return mPlayer->setVideoSurface(surface->getISurface()); } @@ -219,7 +219,7 @@ status_t MediaPlayer::prepare() { LOGV("prepare"); Mutex::Autolock _l(mLock); - if (mPrepareSync) return UNKNOWN_ERROR; + if (mPrepareSync) return -EALREADY; mPrepareSync = true; status_t ret = prepareAsync_l(); if (ret != NO_ERROR) return ret; @@ -253,7 +253,6 @@ status_t MediaPlayer::start() status_t ret = mPlayer->start(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { LOGV("playback completed immediately following start()"); @@ -275,7 +274,6 @@ status_t MediaPlayer::stop() status_t ret = mPlayer->stop(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_STOPPED; } @@ -295,7 +293,6 @@ status_t MediaPlayer::pause() status_t ret = mPlayer->pause(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_PAUSED; } @@ -422,7 +419,6 @@ status_t MediaPlayer::reset() if (ret != NO_ERROR) { LOGE("reset() failed with return code (%d)", ret); mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_IDLE; } |