diff options
author | ST-Ericsson <void@stericsson.com> | 2012-04-20 13:20:30 +0200 |
---|---|---|
committer | Patrik Ryd <patrik.ryd@linaro.org> | 2012-05-09 19:14:22 +0200 |
commit | 4731047ff0e46763a3d54ee83326a230a1a387df (patch) | |
tree | b6347e14e228fcf5dc92f0d62ea184beb0a86056 | |
parent | 06d0b9b37d168dd0520398057373116018d94c2a (diff) | |
download | base-4731047ff0e46763a3d54ee83326a230a1a387df.tar.gz |
Adapt the audio output latency to Android 4.0.4
Signed-off-by: Patrik Ryd <patrik.ryd@stericsson.com>
(cherry picked from commit 0e1230168bd6d0f27ad51a469a06a0ad02f2c4aa)
Change-Id: If3c1a1138b463be2bd337c083cccef3bca27355a
Signed-off-by: Patrik Ryd <patrik.ryd@linaro.org>
-rw-r--r-- | include/media/AudioParameter.h | 2 | ||||
-rw-r--r-- | include/media/AudioSystem.h | 11 | ||||
-rw-r--r-- | include/media/AudioTrack.h | 7 | ||||
-rw-r--r-- | include/media/stagefright/AudioPlayer.h | 1 | ||||
-rw-r--r-- | media/libmedia/AudioParameter.cpp | 2 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 17 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 34 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 1 | ||||
-rw-r--r-- | media/libstagefright/AudioPlayer.cpp | 16 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 9 |
11 files changed, 57 insertions, 49 deletions
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h index 86b0e13dd2cf..bf8c1aeaee36 100644 --- a/include/media/AudioParameter.h +++ b/include/media/AudioParameter.h @@ -46,7 +46,7 @@ public: static const char *keyChannels; static const char *keyFrameCount; static const char *keyInputSource; - static const char *keyLatency; + static const char *keySinkLatency; String8 toString(); diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 2072dced5cac..6d6cf55e7b36 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -30,7 +30,8 @@ namespace android { typedef void (*audio_error_callback)(status_t err); -typedef void (*latency_update_callback)(void *cookie, audio_io_handle_t output, uint32_t latency); +typedef void (*latency_update_callback)(void *cookie, audio_io_handle_t output, uint32_t sinkLatency); + class IAudioPolicyService; class String8; @@ -110,7 +111,8 @@ public: static int newAudioSessionId(); static void acquireAudioSessionId(int audioSession); static void releaseAudioSessionId(int audioSession); - static int registerLatencyNotificationClient(latency_update_callback cb, void *cookie); + + static int registerLatencyNotificationClient(latency_update_callback cb, void *cookie, audio_io_handle_t output); static void unregisterLatencyNotificationClient(int clientId); // types of io configuration change events received with ioConfigChanged() @@ -122,6 +124,7 @@ public: INPUT_CLOSED, INPUT_CONFIG_CHANGED, STREAM_CONFIG_CHANGED, + SINK_LATENCY_CHANGED, NUM_CONFIG_EVENTS }; @@ -226,7 +229,8 @@ private: struct NotificationClient : public RefBase { latency_update_callback mCb; - void * mCookie; + void *mCookie; + audio_io_handle_t mOutput; }; static sp<AudioFlingerClient> gAudioFlingerClient; @@ -251,6 +255,7 @@ private: // list of output descriptors containing cached parameters // (sampling rate, framecount, channel count...) static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs; + static Mutex gLatencyLock; static int gNextUniqueLatencyId; static DefaultKeyedVector<int, sp<AudioSystem::NotificationClient> > gLatencyNotificationClients; diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index eaea86c91aaa..6fb42197f8e9 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -56,7 +56,7 @@ public: EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()). EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()). EVENT_BUFFER_END = 5, // Playback head is at the end of the buffer. - EVENT_LATENCY_CHANGED = 6 // Audio output has been reconfigured and latency has changed. + EVENT_LATENCY_CHANGED = 6 // Audio sink latency has changed. }; /* Create Buffer on the stack and pass it to obtainBuffer() @@ -452,8 +452,9 @@ private: status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount); audio_io_handle_t getOutput_l(); status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart); - static void LatencyCallbackWrapper(void *cookie, audio_io_handle_t output, uint32_t latency); - void latencyCallback(audio_io_handle_t output, uint32_t latency); + + static void LatencyCallback(void *cookie, audio_io_handle_t output, + uint32_t sinkLatency); sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index c878bee9883c..0fdb2971cfe8 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -101,6 +101,7 @@ private: static size_t AudioSinkCallback( MediaPlayerBase::AudioSink *audioSink, void *data, size_t size, void *me); + static void LatencyCallback(uint32_t latency, void *cookie); size_t fillBuffer(void *data, size_t size); diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp index 8d6b71be28f4..49f6e2ab18d1 100644 --- a/media/libmedia/AudioParameter.cpp +++ b/media/libmedia/AudioParameter.cpp @@ -29,7 +29,7 @@ const char *AudioParameter::keyFormat = "format"; const char *AudioParameter::keyChannels = "channels"; const char *AudioParameter::keyFrameCount = "frame_count"; const char *AudioParameter::keyInputSource = "input_source"; -const char *AudioParameter::keyLatency = "latency"; +const char *AudioParameter::keySinkLatency = "sink_latency"; AudioParameter::AudioParameter(const String8& keyValuePairs) { diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index e300af24f412..7e83b819e951 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -374,12 +374,14 @@ void AudioSystem::releaseAudioSessionId(int audioSession) { } } -int AudioSystem::registerLatencyNotificationClient(latency_update_callback cb, void *cookie) { +int AudioSystem::registerLatencyNotificationClient(latency_update_callback cb, + void *cookie, audio_io_handle_t output) { Mutex::Autolock _l(gLatencyLock); sp<NotificationClient> notificationClient = new NotificationClient(); notificationClient->mCb = cb; notificationClient->mCookie = cookie; + notificationClient->mOutput = output; gNextUniqueLatencyId++; gLatencyNotificationClients.add(gNextUniqueLatencyId, notificationClient); @@ -390,6 +392,7 @@ void AudioSystem::unregisterLatencyNotificationClient(int clientId) { Mutex::Autolock _l(gLatencyLock); gLatencyNotificationClients.removeItem(clientId); } + // --------------------------------------------------------------------------- void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) { @@ -469,20 +472,20 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, int ioHandle, v ioHandle, desc->samplingRate, desc->format, desc->channels, desc->frameCount, desc->latency); OutputDescriptor *outputDesc = gOutputs.valueAt(index); - uint32_t oldLatency = outputDesc->latency; delete outputDesc; outputDesc = new OutputDescriptor(*desc); gOutputs.replaceValueFor(ioHandle, outputDesc); - if (oldLatency == outputDesc->latency) { - break; - } - uint32_t newLatency = outputDesc->latency; + } break; + case SINK_LATENCY_CHANGED: { + int sinkLatency = *((int*)param2); gLock.unlock(); gLatencyLock.lock(); size_t size = gLatencyNotificationClients.size(); for (size_t i = 0; i < size; i++) { sp<NotificationClient> client = gLatencyNotificationClients.valueAt(i); - (*client->mCb)(client->mCookie, ioHandle, newLatency); + if (client->mOutput == ioHandle) { + (*client->mCb)(client->mCookie, ioHandle, sinkLatency); + } } gLatencyLock.unlock(); gLock.lock(); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 2f7b011a2d6c..329542b22627 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -124,6 +124,8 @@ AudioTrack::~AudioTrack() LOGV_IF(mSharedBuffer != 0, "Destructor sharedBuffer: %p", mSharedBuffer->pointer()); if (mStatus == NO_ERROR) { + AudioSystem::unregisterLatencyNotificationClient(mLatencyClientId); + // Make sure that callback function exits in the case where // it is looping on buffer full condition in obtainBuffer(). // Otherwise the callback thread will never exit. @@ -136,7 +138,6 @@ AudioTrack::~AudioTrack() IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId); } - AudioSystem::unregisterLatencyNotificationClient(mLatencyClientId); } status_t AudioTrack::set( @@ -264,8 +265,6 @@ status_t AudioTrack::set( mFlags = flags; AudioSystem::acquireAudioSessionId(mSessionId); mRestoreStatus = NO_ERROR; - mLatencyClientId = AudioSystem::registerLatencyNotificationClient( - &AudioTrack::LatencyCallbackWrapper, this); return NO_ERROR; } @@ -823,6 +822,13 @@ status_t AudioTrack::createTrack_l( mCblk->waitTimeMs = 0; mRemainingFrames = mNotificationFramesAct; mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; + + if (mLatencyClientId != -1) { + AudioSystem::unregisterLatencyNotificationClient(mLatencyClientId); + } + mLatencyClientId = AudioSystem::registerLatencyNotificationClient( + &AudioTrack::LatencyCallback, this, output); + return NO_ERROR; } @@ -1282,24 +1288,12 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const } // static -void AudioTrack::LatencyCallbackWrapper(void *cookie, audio_io_handle_t output, uint32_t latency) +void AudioTrack::LatencyCallback(void *cookie, audio_io_handle_t output, uint32_t sinkLatency) { - static_cast<AudioTrack *>(cookie)->latencyCallback(output, latency); -} - -void AudioTrack::latencyCallback(audio_io_handle_t output, uint32_t latency) -{ - audio_io_handle_t myOutput = getOutput(); - if (output != myOutput) { - return; - } - - uint32_t oldLatency = mLatency; - mLatency = latency + (1000*mCblk->frameCount) / mCblk->sampleRate; - LOGV("new latency for output %d (old latency %d, new latency %d)", output, oldLatency, mLatency); - - if (mCbf != NULL) { - mCbf(EVENT_LATENCY_CHANGED, mUserData, &mLatency); + AudioTrack *me = static_cast<AudioTrack *>(cookie); + uint32_t syncLatency = me->mLatency + sinkLatency; + if (me->mCbf != NULL) { + me->mCbf(EVENT_LATENCY_CHANGED, me->mUserData, &syncLatency); } } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 72bb1bcb3ccb..1b78c23d1571 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1515,12 +1515,12 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( } else if (event == AudioTrack::EVENT_LATENCY_CHANGED) { AudioOutput *me = (AudioOutput *)cookie; - uint32_t *newLatency = (uint32_t *)info; - me->mLatency = *newLatency; + uint32_t *syncLatency = (uint32_t *)info; if (me->mLatencyCallback != NULL) { - (*me->mLatencyCallback)(*newLatency, me->mCallbackCookie); + (*me->mLatencyCallback)(*syncLatency, me->mCallbackCookie); } } + } int MediaPlayerService::AudioOutput::getSessionId() diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 95176f512940..095707054abc 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -86,6 +86,7 @@ class MediaPlayerService : public BnMediaPlayerService int format, int bufferCount, AudioCallback cb, void *cookie, LatencyCallback latencyCb = NULL); + virtual void start(); virtual ssize_t write(const void* buffer, size_t size); virtual void stop(); diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index 79210e4de8fa..796d1b151da2 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -261,7 +261,10 @@ void AudioPlayer::LatencyCallback(uint32_t latency, void *cookie) { AudioPlayer *me = (AudioPlayer *)cookie; int64_t oldLatency = me->mLatencyUs; me->mLatencyUs = (int64_t)latency * 1000; - LOGI("Audio output latency updated from %lldus to %lldus", oldLatency, me->mLatencyUs); + if (oldLatency != me->mLatencyUs) { + LOGI("Audio output latency updated from %lldus to %lldus", + oldLatency, me->mLatencyUs); + } } bool AudioPlayer::isSeeking() { @@ -288,15 +291,18 @@ size_t AudioPlayer::AudioSinkCallback( void AudioPlayer::AudioCallback(int event, void *info) { if (event == AudioTrack::EVENT_MORE_DATA) { - AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; - size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); + AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; + size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); - buffer->size = numBytesWritten; + buffer->size = numBytesWritten; } else if (event == AudioTrack::EVENT_LATENCY_CHANGED) { uint32_t *newLatency = (uint32_t *)info; int64_t oldLatency = mLatencyUs; mLatencyUs = (int64_t)*newLatency * 1000; - LOGI("Audio output latency updated from %lldus to %lldus", oldLatency, mLatencyUs); + if (oldLatency != mLatencyUs) { + LOGI("Audio output latency updated from %lldus to %lldus", + oldLatency, mLatencyUs); + } } } diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 7edf2b2c719f..eff6ad687727 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1712,6 +1712,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { break; case AudioSystem::STREAM_CONFIG_CHANGED: + case AudioSystem::SINK_LATENCY_CHANGED: param2 = ¶m; case AudioSystem::OUTPUT_CLOSED: default: @@ -2347,7 +2348,6 @@ void AudioFlinger::MixerThread::deleteTrackName_l(int name) bool AudioFlinger::MixerThread::checkForNewParameters_l() { bool reconfig = false; - bool updateLatency = false; while (!mNewParameters.isEmpty()) { status_t status = NO_ERROR; @@ -2411,8 +2411,8 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() mEffectChains[i]->setDevice_l(mDevice); } } - if (param.getInt(String8(AudioParameter::keyLatency), value) == NO_ERROR) { - updateLatency = true; + if (param.getInt(String8(AudioParameter::keySinkLatency), value) == NO_ERROR) { + sendConfigEvent_l(AudioSystem::SINK_LATENCY_CHANGED, value); } if (status == NO_ERROR) { @@ -2440,9 +2440,6 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() } sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED); } - if (status == NO_ERROR && updateLatency) { - sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED); - } } mNewParameters.removeAt(0); |