summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorST-Ericsson <void@stericsson.com>2012-04-20 13:20:30 +0200
committerPatrik Ryd <patrik.ryd@linaro.org>2012-05-09 19:14:22 +0200
commit4731047ff0e46763a3d54ee83326a230a1a387df (patch)
treeb6347e14e228fcf5dc92f0d62ea184beb0a86056
parent06d0b9b37d168dd0520398057373116018d94c2a (diff)
downloadbase-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.h2
-rw-r--r--include/media/AudioSystem.h11
-rw-r--r--include/media/AudioTrack.h7
-rw-r--r--include/media/stagefright/AudioPlayer.h1
-rw-r--r--media/libmedia/AudioParameter.cpp2
-rw-r--r--media/libmedia/AudioSystem.cpp17
-rw-r--r--media/libmedia/AudioTrack.cpp34
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp6
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h1
-rw-r--r--media/libstagefright/AudioPlayer.cpp16
-rw-r--r--services/audioflinger/AudioFlinger.cpp9
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 = &param;
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);