diff options
-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 b42bf54..42bb4df 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 b689dcb..bddd23e 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 6575da6..588c51a 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 c07bbfe..747d0e4 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 530e432..48154f9 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 858e5aa..30e2bc9 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 1136ce1..5b9a6b1 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 5c58603..cad420a 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 52999b1..44da9ed 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 57874f3..d63c031 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 42da413..95c7ea3 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 ae391ee..ae215d1 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 583f852..769ae3f 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 e3b829b..c5dfbb5 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 fc42979..ca3a2a6 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 af8d1b5..5b061b1 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 d1206b4..d243b96 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, |