diff options
author | 2010-01-19 17:37:09 -0800 | |
---|---|---|
committer | 2010-01-26 18:40:39 -0800 | |
commit | 0986e7907ffc8387b04fb201e285784bcd11b9b7 (patch) | |
tree | 96733235d1e92e0f329ded11b9b55c0d67a4ca83 | |
parent | 7d3a558b9ebf2256517ec99cd09c066cc7dbc92c (diff) |
Fix issue 2285561: New AudioFlinger and audio driver API needed for A/V sync
Added getRenderPosition() API to IAudioFlinger to retreive number of audio frames
written by AudioFlinger to audio HAL and by DSP to DAC.
Added getRenderPosition() API to AudioHardwareInterface to retreive number of audio frames
written by DSP to DAC.
Exposed AudioTrack::getPosition() to AudioSink() to make it available to media player.
Removed excessive log in AudioHardwareGeneric.
-rw-r--r-- | include/media/AudioSystem.h | 11 | ||||
-rw-r--r-- | include/media/IAudioFlinger.h | 1 | ||||
-rw-r--r-- | include/media/MediaPlayerInterface.h | 1 | ||||
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.cpp | 6 | ||||
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.h | 1 | ||||
-rw-r--r-- | libs/audioflinger/AudioDumpInterface.cpp | 6 | ||||
-rw-r--r-- | libs/audioflinger/AudioDumpInterface.h | 3 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 33 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.h | 3 | ||||
-rw-r--r-- | libs/audioflinger/AudioHardwareGeneric.cpp | 12 | ||||
-rw-r--r-- | libs/audioflinger/AudioHardwareGeneric.h | 1 | ||||
-rw-r--r-- | libs/audioflinger/AudioHardwareStub.cpp | 5 | ||||
-rw-r--r-- | libs/audioflinger/AudioHardwareStub.h | 1 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 12 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 36 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 13 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 2 |
17 files changed, 137 insertions, 10 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index b42bf5477f7b..42bb4df4177a 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -222,6 +222,17 @@ public: static status_t setVoiceVolume(float volume); + // return the number of audio frames written by AudioFlinger to audio HAL and + // audio dsp to DAC since the output on which the specificed stream is playing + // has exited standby. + // returned status (from utils/Errors.h) can be: + // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data + // - INVALID_OPERATION: Not supported on current hardware platform + // - BAD_VALUE: invalid parameter + // NOTE: this feature is not supported on all hardware platforms and it is + // necessary to check returned status before using the returned values. + static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT); + // // AudioPolicyService interface // diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index b689dcbc1d2e..bddd23e3461f 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -130,6 +130,7 @@ public: virtual status_t setStreamOutput(uint32_t stream, int output) = 0; virtual status_t setVoiceVolume(float volume) = 0; + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0; }; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 6575da6fd12e..588c51adde68 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -72,6 +72,7 @@ public: virtual ssize_t frameSize() const = 0; virtual uint32_t latency() const = 0; virtual float msecsPerFrame() const = 0; + virtual status_t getPosition(uint32_t *position) = 0; // If no callback is specified, use the "write" API below to submit // audio data. Otherwise return a full buffer of audio data on each diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index c07bbfe771d3..747d0e4ce316 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -457,4 +457,10 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<Strin return NO_ERROR; } +status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames) +{ + //TODO: enable when supported by driver + return INVALID_OPERATION; +} + }; // namespace android diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h index 530e432c6a4a..48154f942878 100644 --- a/libs/audioflinger/A2dpAudioInterface.h +++ b/libs/audioflinger/A2dpAudioInterface.h @@ -93,6 +93,7 @@ private: virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys); + virtual status_t getRenderPosition(uint32_t *dspFrames); private: friend class A2dpAudioInterface; diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp index 858e5aab057a..30e2bc9c9b3d 100644 --- a/libs/audioflinger/AudioDumpInterface.cpp +++ b/libs/audioflinger/AudioDumpInterface.cpp @@ -379,6 +379,12 @@ void AudioStreamOutDump::Close() } } +status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames) +{ + if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames); + return INVALID_OPERATION; +} + // ---------------------------------------------------------------------------- AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface, diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h index 1136ce1bcb25..5b9a6b1434d8 100644 --- a/libs/audioflinger/AudioDumpInterface.h +++ b/libs/audioflinger/AudioDumpInterface.h @@ -56,8 +56,9 @@ public: void Close(void); AudioStreamOut* finalStream() { return mFinalStream; } uint32_t device() { return mDevice; } - int getId() { return mId; } + virtual status_t getRenderPosition(uint32_t *dspFrames); + private: AudioDumpInterface *mInterface; int mId; diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 5c58603fae12..cad420a9b153 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -633,6 +633,20 @@ status_t AudioFlinger::setVoiceVolume(float value) return ret; } +status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) +{ + status_t status; + + Mutex::Autolock _l(mLock); + + PlaybackThread *playbackThread = checkPlaybackThread_l(output); + if (playbackThread != NULL) { + return playbackThread->getRenderPosition(halFrames, dspFrames); + } + + return BAD_VALUE; +} + void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) { @@ -1166,6 +1180,19 @@ void AudioFlinger::PlaybackThread::readOutputParameters() memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t)); } +status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) +{ + if (halFrames == 0 || dspFrames == 0) { + return BAD_VALUE; + } + if (mOutput == 0) { + return INVALID_OPERATION; + } + *halFrames = mBytesWritten/mOutput->frameSize(); + + return mOutput->getRenderPosition(dspFrames); +} + // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) @@ -1290,8 +1317,9 @@ bool AudioFlinger::MixerThread::threadLoop() if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; + mBytesWritten += mixBufferSize; int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); - if (bytesWritten > 0) mBytesWritten += bytesWritten; + if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; nsecs_t now = systemTime(); @@ -1812,8 +1840,9 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (sleepTime == 0) { mLastWriteTime = systemTime(); mInWrite = true; + mBytesWritten += mixBufferSize; int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); - if (bytesWritten) mBytesWritten += bytesWritten; + if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; mStandby = false; diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 52999b13a914..44da9ed45646 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -136,6 +136,8 @@ public: virtual status_t setVoiceVolume(float volume); + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output); + // IBinder::DeathRecipient virtual void binderDied(const wp<IBinder>& who); @@ -526,6 +528,7 @@ private: bool isSuspended() { return (mSuspended != 0); } virtual String8 getParameters(const String8& keys); virtual void audioConfigChanged(int event, int param = 0); + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); struct stream_type_t { stream_type_t() diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp index 57874f3ce1ab..d63c0318d4a8 100644 --- a/libs/audioflinger/AudioHardwareGeneric.cpp +++ b/libs/audioflinger/AudioHardwareGeneric.cpp @@ -298,6 +298,11 @@ String8 AudioStreamOutGeneric::getParameters(const String8& keys) return param.toString(); } +status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames) +{ + return INVALID_OPERATION; +} + // ---------------------------------------------------------------------------- // record functions @@ -310,9 +315,8 @@ status_t AudioStreamInGeneric::set( uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics) { - // FIXME: remove logging if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE; - LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate); + LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate); // check values if ((*pFormat != format()) || (*pChannels != channels()) || @@ -332,14 +336,10 @@ status_t AudioStreamInGeneric::set( AudioStreamInGeneric::~AudioStreamInGeneric() { - // FIXME: remove logging - LOGD("AudioStreamInGeneric destructor"); } ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes) { - // FIXME: remove logging - LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, (int)bytes, mFd); AutoMutex lock(mLock); if (mFd < 0) { LOGE("Attempt to read from unopened device"); diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h index 42da413e8f0f..95c7ea37a422 100644 --- a/libs/audioflinger/AudioHardwareGeneric.h +++ b/libs/audioflinger/AudioHardwareGeneric.h @@ -55,6 +55,7 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys); + virtual status_t getRenderPosition(uint32_t *dspFrames); private: AudioHardwareGeneric *mAudioHardware; diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp index ae391ee561d0..ae215d10fa66 100644 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ b/libs/audioflinger/AudioHardwareStub.cpp @@ -158,6 +158,11 @@ String8 AudioStreamOutStub::getParameters(const String8& keys) return param.toString(); } +status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames) +{ + return INVALID_OPERATION; +} + // ---------------------------------------------------------------------------- status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h index 583f852b5bd9..769ae3fbddae 100644 --- a/libs/audioflinger/AudioHardwareStub.h +++ b/libs/audioflinger/AudioHardwareStub.h @@ -41,6 +41,7 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;} virtual String8 getParameters(const String8& keys); + virtual status_t getRenderPosition(uint32_t *dspFrames); }; class AudioStreamInStub : public AudioStreamIn { diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index e3b829be3d61..c5dfbb5356fe 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -342,6 +342,18 @@ status_t AudioSystem::setVoiceVolume(float value) return af->setVoiceVolume(value); } +status_t AudioSystem::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream) +{ + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + + if (stream == DEFAULT) { + stream = MUSIC; + } + + return af->getRenderPosition(halFrames, dspFrames, getOutput((stream_type)stream)); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index fc42979446ed..ca3a2a600f8f 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -60,7 +60,8 @@ enum { OPEN_INPUT, CLOSE_INPUT, SET_STREAM_OUTPUT, - SET_VOICE_VOLUME + SET_VOICE_VOLUME, + GET_RENDER_POSITION }; class BpAudioFlinger : public BpInterface<IAudioFlinger> @@ -466,6 +467,26 @@ public: remote()->transact(SET_VOICE_VOLUME, data, &reply); return reply.readInt32(); } + + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(GET_RENDER_POSITION, data, &reply); + status_t status = reply.readInt32(); + if (status == NO_ERROR) { + uint32_t tmp = reply.readInt32(); + if (halFrames) { + *halFrames = tmp; + } + tmp = reply.readInt32(); + if (dspFrames) { + *dspFrames = tmp; + } + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -718,6 +739,19 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( setVoiceVolume(volume) ); return NO_ERROR; } break; + case GET_RENDER_POSITION: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + uint32_t halFrames; + uint32_t dspFrames; + status_t status = getRenderPosition(&halFrames, &dspFrames, output); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(halFrames); + reply->writeInt32(dspFrames); + } + return NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index af8d1b56b160..5b061b128ab1 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1432,6 +1432,12 @@ float MediaPlayerService::AudioOutput::msecsPerFrame() const return mMsecsPerFrame; } +status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) +{ + if (mTrack == 0) return NO_INIT; + return mTrack->getPosition(position); +} + status_t MediaPlayerService::AudioOutput::open( uint32_t sampleRate, int channelCount, int format, int bufferCount, AudioCallback cb, void *cookie) @@ -1613,6 +1619,13 @@ float MediaPlayerService::AudioCache::msecsPerFrame() const return mMsecsPerFrame; } +status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) +{ + if (position == 0) return BAD_VALUE; + *position = mSize; + return NO_ERROR; +} + status_t MediaPlayerService::AudioCache::open( uint32_t sampleRate, int channelCount, int format, int bufferCount, AudioCallback cb, void *cookie) diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index d1206b46f7e5..d243b9638f55 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -76,6 +76,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual ssize_t frameSize() const; virtual uint32_t latency() const; virtual float msecsPerFrame() const; + virtual status_t getPosition(uint32_t *position); virtual status_t open( uint32_t sampleRate, int channelCount, @@ -130,6 +131,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); } virtual uint32_t latency() const; virtual float msecsPerFrame() const; + virtual status_t getPosition(uint32_t *position); virtual status_t open( uint32_t sampleRate, int channelCount, int format, |