Loading include/media/AudioTrack.h +20 −0 Original line number Diff line number Diff line Loading @@ -771,6 +771,9 @@ public: * Use getTimestamp(AudioTimestamp& timestamp) instead. */ status_t getTimestamp(ExtendedTimestamp *timestamp); private: status_t getTimestamp_l(ExtendedTimestamp *timestamp); public: /* Add an AudioDeviceCallback. The caller will be notified when the audio device to which this * AudioTrack is routed is updated. Loading @@ -794,6 +797,23 @@ public: status_t removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback); /* Obtain the pending duration in milliseconds for playback of pure PCM * (mixable without embedded timing) data remaining in AudioTrack. * * This is used to estimate the drain time for the client-server buffer * so the choice of ExtendedTimestamp::LOCATION_SERVER is default. * One may optionally request to find the duration to play through the HAL * by specifying a location ExtendedTimestamp::LOCATION_KERNEL; however, * INVALID_OPERATION may be returned if the kernel location is unavailable. * * Returns NO_ERROR if successful. * INVALID_OPERATION if ExtendedTimestamp::LOCATION_KERNEL cannot be obtained * or the AudioTrack does not contain pure PCM data. * BAD_VALUE if msec is nullptr or location is invalid. */ status_t pendingDuration(int32_t *msec, ExtendedTimestamp::Location location = ExtendedTimestamp::LOCATION_SERVER); protected: /* copying audio tracks is not allowed */ AudioTrack(const AudioTrack& other); Loading media/libmedia/AudioTrack.cpp +55 −0 Original line number Diff line number Diff line Loading @@ -2188,6 +2188,11 @@ status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp) return BAD_VALUE; } AutoMutex lock(mLock); return getTimestamp_l(timestamp); } status_t AudioTrack::getTimestamp_l(ExtendedTimestamp *timestamp) { if (mCblk->mFlags & CBLK_INVALID) { const status_t status = restoreTrack_l("getTimestampExtended"); if (status != OK) { Loading Loading @@ -2515,6 +2520,56 @@ status_t AudioTrack::removeAudioDeviceCallback( return NO_ERROR; } status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location) { if (msec == nullptr || (location != ExtendedTimestamp::LOCATION_SERVER && location != ExtendedTimestamp::LOCATION_KERNEL)) { return BAD_VALUE; } AutoMutex lock(mLock); // inclusive of offloaded and direct tracks. // // It is possible, but not enabled, to allow duration computation for non-pcm // audio_has_proportional_frames() formats because currently they have // the drain rate equivalent to the pcm sample rate * framesize. if (!isPurePcmData_l()) { return INVALID_OPERATION; } ExtendedTimestamp ets; if (getTimestamp_l(&ets) == OK && ets.mTimeNs[location] > 0) { int64_t diff = ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT] - ets.mPosition[location]; if (diff < 0) { *msec = 0; } else { // ms is the playback time by frames int64_t ms = (int64_t)((double)diff * 1000 / ((double)mSampleRate * mPlaybackRate.mSpeed)); // clockdiff is the timestamp age (negative) int64_t clockdiff = (mState != STATE_ACTIVE) ? 0 : ets.mTimeNs[location] + ets.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_MONOTONIC] - systemTime(SYSTEM_TIME_MONOTONIC); //ALOGV("ms: %lld clockdiff: %lld", (long long)ms, (long long)clockdiff); static const int NANOS_PER_MILLIS = 1000000; *msec = (int32_t)(ms + clockdiff / NANOS_PER_MILLIS); } return NO_ERROR; } if (location != ExtendedTimestamp::LOCATION_SERVER) { return INVALID_OPERATION; // LOCATION_KERNEL is not available } // use server position directly (offloaded and direct arrive here) updateAndGetPosition_l(); int32_t diff = (Modulo<uint32_t>(mFramesWritten) - mPosition).signedValue(); *msec = (diff <= 0) ? 0 : (int32_t)((double)diff * 1000 / ((double)mSampleRate * mPlaybackRate.mSpeed)); return NO_ERROR; } // ========================================================================= void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused) Loading media/libmediaplayerservice/MediaPlayerService.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -1578,7 +1578,19 @@ void MediaPlayerService::AudioOutput::deleteRecycledTrack_l() } if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) { mRecycledTrack->flush(); int32_t msec = 0; if (!mRecycledTrack->stopped()) { // check if active (void)mRecycledTrack->pendingDuration(&msec); } mRecycledTrack->stop(); // ensure full data drain ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec); if (msec > 0) { static const int32_t WAIT_LIMIT_MS = 3000; if (msec > WAIT_LIMIT_MS) { msec = WAIT_LIMIT_MS; } usleep(msec * 1000LL); } } // An offloaded track isn't flushed because the STREAM_END is reported // slightly prematurely to allow time for the gapless track switch Loading Loading
include/media/AudioTrack.h +20 −0 Original line number Diff line number Diff line Loading @@ -771,6 +771,9 @@ public: * Use getTimestamp(AudioTimestamp& timestamp) instead. */ status_t getTimestamp(ExtendedTimestamp *timestamp); private: status_t getTimestamp_l(ExtendedTimestamp *timestamp); public: /* Add an AudioDeviceCallback. The caller will be notified when the audio device to which this * AudioTrack is routed is updated. Loading @@ -794,6 +797,23 @@ public: status_t removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback); /* Obtain the pending duration in milliseconds for playback of pure PCM * (mixable without embedded timing) data remaining in AudioTrack. * * This is used to estimate the drain time for the client-server buffer * so the choice of ExtendedTimestamp::LOCATION_SERVER is default. * One may optionally request to find the duration to play through the HAL * by specifying a location ExtendedTimestamp::LOCATION_KERNEL; however, * INVALID_OPERATION may be returned if the kernel location is unavailable. * * Returns NO_ERROR if successful. * INVALID_OPERATION if ExtendedTimestamp::LOCATION_KERNEL cannot be obtained * or the AudioTrack does not contain pure PCM data. * BAD_VALUE if msec is nullptr or location is invalid. */ status_t pendingDuration(int32_t *msec, ExtendedTimestamp::Location location = ExtendedTimestamp::LOCATION_SERVER); protected: /* copying audio tracks is not allowed */ AudioTrack(const AudioTrack& other); Loading
media/libmedia/AudioTrack.cpp +55 −0 Original line number Diff line number Diff line Loading @@ -2188,6 +2188,11 @@ status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp) return BAD_VALUE; } AutoMutex lock(mLock); return getTimestamp_l(timestamp); } status_t AudioTrack::getTimestamp_l(ExtendedTimestamp *timestamp) { if (mCblk->mFlags & CBLK_INVALID) { const status_t status = restoreTrack_l("getTimestampExtended"); if (status != OK) { Loading Loading @@ -2515,6 +2520,56 @@ status_t AudioTrack::removeAudioDeviceCallback( return NO_ERROR; } status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location) { if (msec == nullptr || (location != ExtendedTimestamp::LOCATION_SERVER && location != ExtendedTimestamp::LOCATION_KERNEL)) { return BAD_VALUE; } AutoMutex lock(mLock); // inclusive of offloaded and direct tracks. // // It is possible, but not enabled, to allow duration computation for non-pcm // audio_has_proportional_frames() formats because currently they have // the drain rate equivalent to the pcm sample rate * framesize. if (!isPurePcmData_l()) { return INVALID_OPERATION; } ExtendedTimestamp ets; if (getTimestamp_l(&ets) == OK && ets.mTimeNs[location] > 0) { int64_t diff = ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT] - ets.mPosition[location]; if (diff < 0) { *msec = 0; } else { // ms is the playback time by frames int64_t ms = (int64_t)((double)diff * 1000 / ((double)mSampleRate * mPlaybackRate.mSpeed)); // clockdiff is the timestamp age (negative) int64_t clockdiff = (mState != STATE_ACTIVE) ? 0 : ets.mTimeNs[location] + ets.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_MONOTONIC] - systemTime(SYSTEM_TIME_MONOTONIC); //ALOGV("ms: %lld clockdiff: %lld", (long long)ms, (long long)clockdiff); static const int NANOS_PER_MILLIS = 1000000; *msec = (int32_t)(ms + clockdiff / NANOS_PER_MILLIS); } return NO_ERROR; } if (location != ExtendedTimestamp::LOCATION_SERVER) { return INVALID_OPERATION; // LOCATION_KERNEL is not available } // use server position directly (offloaded and direct arrive here) updateAndGetPosition_l(); int32_t diff = (Modulo<uint32_t>(mFramesWritten) - mPosition).signedValue(); *msec = (diff <= 0) ? 0 : (int32_t)((double)diff * 1000 / ((double)mSampleRate * mPlaybackRate.mSpeed)); return NO_ERROR; } // ========================================================================= void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused) Loading
media/libmediaplayerservice/MediaPlayerService.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -1578,7 +1578,19 @@ void MediaPlayerService::AudioOutput::deleteRecycledTrack_l() } if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) { mRecycledTrack->flush(); int32_t msec = 0; if (!mRecycledTrack->stopped()) { // check if active (void)mRecycledTrack->pendingDuration(&msec); } mRecycledTrack->stop(); // ensure full data drain ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec); if (msec > 0) { static const int32_t WAIT_LIMIT_MS = 3000; if (msec > WAIT_LIMIT_MS) { msec = WAIT_LIMIT_MS; } usleep(msec * 1000LL); } } // An offloaded track isn't flushed because the STREAM_END is reported // slightly prematurely to allow time for the gapless track switch Loading