Loading media/libmedia/AudioTrack.cpp +47 −10 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ static inline const T &max(const T &x, const T &y) { return x > y ? x : y; } static const int32_t NANOS_PER_SECOND = 1000000000; static inline nsecs_t framesToNanoseconds(ssize_t frames, uint32_t sampleRate, float speed) { return ((double)frames * 1000000000) / ((double)sampleRate * speed); Loading @@ -60,6 +62,11 @@ static int64_t convertTimespecToUs(const struct timespec &tv) return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000; } static inline nsecs_t convertTimespecToNs(const struct timespec &tv) { return tv.tv_sec * (long long)NANOS_PER_SECOND + tv.tv_nsec; } // current monotonic time in microseconds. static int64_t getNowUs() { Loading Loading @@ -2399,6 +2406,26 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER, "getTimestamp() location moved from server to kernel"); } // We update the timestamp time even when paused. if (mState == STATE_PAUSED /* not needed: STATE_PAUSED_STOPPING */) { const int64_t now = systemTime(); const int64_t at = convertTimespecToNs(timestamp.mTime); const int64_t lag = (ets.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] < 0 || ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] < 0) ? int64_t(mAfLatency * 1000000LL) : (ets.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] - ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK]) * NANOS_PER_SECOND / mSampleRate; const int64_t limit = now - lag; // no earlier than this limit if (at < limit) { ALOGV("timestamp pause lag:%lld adjusting from %lld to %lld", (long long)lag, (long long)at, (long long)limit); timestamp.mTime.tv_sec = limit / NANOS_PER_SECOND; timestamp.mTime.tv_nsec = limit % NANOS_PER_SECOND; // compiler opt. } } mPreviousLocation = location; } else { // right after AudioTrack is started, one may not find a timestamp Loading Loading @@ -2428,6 +2455,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) // use cached paused position in case another offloaded track is running. timestamp.mPosition = mPausedPosition; clock_gettime(CLOCK_MONOTONIC, ×tamp.mTime); // TODO: adjust for delay return NO_ERROR; } Loading Loading @@ -2514,21 +2542,18 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) // This is sometimes caused by erratic reports of the available space in the ALSA drivers. if (status == NO_ERROR) { if (previousTimestampValid) { #define TIME_TO_NANOS(time) ((int64_t)(time).tv_sec * 1000000000 + (time).tv_nsec) const int64_t previousTimeNanos = TIME_TO_NANOS(mPreviousTimestamp.mTime); const int64_t currentTimeNanos = TIME_TO_NANOS(timestamp.mTime); #undef TIME_TO_NANOS const int64_t previousTimeNanos = convertTimespecToNs(mPreviousTimestamp.mTime); const int64_t currentTimeNanos = convertTimespecToNs(timestamp.mTime); if (currentTimeNanos < previousTimeNanos) { ALOGW("retrograde timestamp time"); // FIXME Consider blocking this from propagating upwards. ALOGW("retrograde timestamp time corrected, %lld < %lld", (long long)currentTimeNanos, (long long)previousTimeNanos); timestamp.mTime = mPreviousTimestamp.mTime; } // Looking at signed delta will work even when the timestamps // are wrapping around. int32_t deltaPosition = (Modulo<uint32_t>(timestamp.mPosition) - mPreviousTimestamp.mPosition).signedValue(); // position can bobble slightly as an artifact; this hides the bobble static const int32_t MINIMUM_POSITION_DELTA = 8; if (deltaPosition < 0) { // Only report once per position instead of spamming the log. if (!mRetrogradeMotionReported) { Loading @@ -2541,9 +2566,21 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } else { mRetrogradeMotionReported = false; } if (deltaPosition < MINIMUM_POSITION_DELTA) { timestamp = mPreviousTimestamp; // Use last valid timestamp. if (deltaPosition < 0) { timestamp.mPosition = mPreviousTimestamp.mPosition; deltaPosition = 0; } #if 0 // Uncomment this to verify audio timestamp rate. const int64_t deltaTime = convertTimespecToNs(timestamp.mTime) - previousTimeNanos; if (deltaTime != 0) { const int64_t computedSampleRate = deltaPosition * (long long)NANOS_PER_SECOND / deltaTime; ALOGD("computedSampleRate:%u sampleRate:%u", (unsigned)computedSampleRate, mSampleRate); } #endif } mPreviousTimestamp = timestamp; mPreviousTimestampValid = true; Loading media/libmediaplayerservice/MediaPlayerService.cpp +13 −25 Original line number Diff line number Diff line Loading @@ -1521,57 +1521,45 @@ int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) c } uint32_t numFramesPlayed; int64_t numFramesPlayedAt; int64_t numFramesPlayedAtUs; AudioTimestamp ts; static const int64_t kStaleTimestamp100ms = 100000; status_t res = mTrack->getTimestamp(ts); if (res == OK) { // case 1: mixing audio tracks and offloaded tracks. numFramesPlayed = ts.mPosition; numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; const int64_t timestampAge = nowUs - numFramesPlayedAt; if (timestampAge > kStaleTimestamp100ms) { // This is an audio FIXME. // getTimestamp returns a timestamp which may come from audio mixing threads. // After pausing, the MixerThread may go idle, thus the mTime estimate may // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms, // the max latency should be about 25ms with an average around 12ms (to be verified). // For safety we use 100ms. ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)", (long long)nowUs, (long long)numFramesPlayedAt); numFramesPlayedAt = nowUs - kStaleTimestamp100ms; } //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track numFramesPlayed = 0; numFramesPlayedAt = nowUs; numFramesPlayedAtUs = nowUs; //ALOGD("getTimestamp: WOULD_BLOCK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else { // case 3: transitory at new track or audio fast tracks. res = mTrack->getPosition(&numFramesPlayed); CHECK_EQ(res, (status_t)OK); numFramesPlayedAt = nowUs; numFramesPlayedAt += 1000LL * mTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = nowUs; numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours. int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz) + nowUs - numFramesPlayedAt; + nowUs - numFramesPlayedAtUs; if (durationUs < 0) { // Occurs when numFramesPlayed position is very small and the following: // (1) In case 1, the time nowUs is computed before getTimestamp() is called and // numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed. // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed. // (2) In case 3, using getPosition and adding mAudioSink->latency() to // numFramesPlayedAt, by a time amount greater than numFramesPlayed. // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed. // // Both of these are transitory conditions. ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs); durationUs = 0; } ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)", (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt); (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAtUs); return durationUs; } Loading media/libstagefright/MediaSync.cpp +12 −28 Original line number Diff line number Diff line Loading @@ -478,59 +478,43 @@ int64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) { CHECK(mAudioTrack != NULL); uint32_t numFramesPlayed; int64_t numFramesPlayedAt; int64_t numFramesPlayedAtUs; AudioTimestamp ts; static const int64_t kStaleTimestamp100ms = 100000; status_t res = mAudioTrack->getTimestamp(ts); if (res == OK) { // case 1: mixing audio tracks. numFramesPlayed = ts.mPosition; numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; const int64_t timestampAge = nowUs - numFramesPlayedAt; if (timestampAge > kStaleTimestamp100ms) { // This is an audio FIXME. // getTimestamp returns a timestamp which may come from audio // mixing threads. After pausing, the MixerThread may go idle, // thus the mTime estimate may become stale. Assuming that the // MixerThread runs 20ms, with FastMixer at 5ms, the max latency // should be about 25ms with an average around 12ms (to be // verified). For safety we use 100ms. ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) " "numFramesPlayedAt(%lld)", (long long)nowUs, (long long)numFramesPlayedAt); numFramesPlayedAt = nowUs - kStaleTimestamp100ms; } numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; //ALOGD("getTimestamp: OK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track numFramesPlayed = 0; numFramesPlayedAt = nowUs; numFramesPlayedAtUs = nowUs; //ALOGD("getTimestamp: WOULD_BLOCK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else { // case 3: transitory at new track or audio fast tracks. res = mAudioTrack->getPosition(&numFramesPlayed); CHECK_EQ(res, (status_t)OK); numFramesPlayedAt = nowUs; numFramesPlayedAt += 1000LL * mAudioTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = nowUs; numFramesPlayedAtUs += 1000LL * mAudioTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } //can't be negative until 12.4 hrs, test. //CHECK_EQ(numFramesPlayed & (1 << 31), 0); int64_t durationUs = getDurationIfPlayedAtNativeSampleRate_l(numFramesPlayed) + nowUs - numFramesPlayedAt; + nowUs - numFramesPlayedAtUs; if (durationUs < 0) { // Occurs when numFramesPlayed position is very small and the following: // (1) In case 1, the time nowUs is computed before getTimestamp() is // called and numFramesPlayedAt is greater than nowUs by time more // called and numFramesPlayedAtUs is greater than nowUs by time more // than numFramesPlayed. // (2) In case 3, using getPosition and adding mAudioTrack->latency() // to numFramesPlayedAt, by a time amount greater than // to numFramesPlayedAtUs, by a time amount greater than // numFramesPlayed. // // Both of these are transitory conditions. Loading @@ -541,7 +525,7 @@ int64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) { ALOGV("getPlayedOutAudioDurationMedia_l(%lld) nowUs(%lld) frames(%u) " "framesAt(%lld)", (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt); (long long)numFramesPlayedAtUs); return durationUs; } Loading Loading
media/libmedia/AudioTrack.cpp +47 −10 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ static inline const T &max(const T &x, const T &y) { return x > y ? x : y; } static const int32_t NANOS_PER_SECOND = 1000000000; static inline nsecs_t framesToNanoseconds(ssize_t frames, uint32_t sampleRate, float speed) { return ((double)frames * 1000000000) / ((double)sampleRate * speed); Loading @@ -60,6 +62,11 @@ static int64_t convertTimespecToUs(const struct timespec &tv) return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000; } static inline nsecs_t convertTimespecToNs(const struct timespec &tv) { return tv.tv_sec * (long long)NANOS_PER_SECOND + tv.tv_nsec; } // current monotonic time in microseconds. static int64_t getNowUs() { Loading Loading @@ -2399,6 +2406,26 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER, "getTimestamp() location moved from server to kernel"); } // We update the timestamp time even when paused. if (mState == STATE_PAUSED /* not needed: STATE_PAUSED_STOPPING */) { const int64_t now = systemTime(); const int64_t at = convertTimespecToNs(timestamp.mTime); const int64_t lag = (ets.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] < 0 || ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] < 0) ? int64_t(mAfLatency * 1000000LL) : (ets.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] - ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK]) * NANOS_PER_SECOND / mSampleRate; const int64_t limit = now - lag; // no earlier than this limit if (at < limit) { ALOGV("timestamp pause lag:%lld adjusting from %lld to %lld", (long long)lag, (long long)at, (long long)limit); timestamp.mTime.tv_sec = limit / NANOS_PER_SECOND; timestamp.mTime.tv_nsec = limit % NANOS_PER_SECOND; // compiler opt. } } mPreviousLocation = location; } else { // right after AudioTrack is started, one may not find a timestamp Loading Loading @@ -2428,6 +2455,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) // use cached paused position in case another offloaded track is running. timestamp.mPosition = mPausedPosition; clock_gettime(CLOCK_MONOTONIC, ×tamp.mTime); // TODO: adjust for delay return NO_ERROR; } Loading Loading @@ -2514,21 +2542,18 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) // This is sometimes caused by erratic reports of the available space in the ALSA drivers. if (status == NO_ERROR) { if (previousTimestampValid) { #define TIME_TO_NANOS(time) ((int64_t)(time).tv_sec * 1000000000 + (time).tv_nsec) const int64_t previousTimeNanos = TIME_TO_NANOS(mPreviousTimestamp.mTime); const int64_t currentTimeNanos = TIME_TO_NANOS(timestamp.mTime); #undef TIME_TO_NANOS const int64_t previousTimeNanos = convertTimespecToNs(mPreviousTimestamp.mTime); const int64_t currentTimeNanos = convertTimespecToNs(timestamp.mTime); if (currentTimeNanos < previousTimeNanos) { ALOGW("retrograde timestamp time"); // FIXME Consider blocking this from propagating upwards. ALOGW("retrograde timestamp time corrected, %lld < %lld", (long long)currentTimeNanos, (long long)previousTimeNanos); timestamp.mTime = mPreviousTimestamp.mTime; } // Looking at signed delta will work even when the timestamps // are wrapping around. int32_t deltaPosition = (Modulo<uint32_t>(timestamp.mPosition) - mPreviousTimestamp.mPosition).signedValue(); // position can bobble slightly as an artifact; this hides the bobble static const int32_t MINIMUM_POSITION_DELTA = 8; if (deltaPosition < 0) { // Only report once per position instead of spamming the log. if (!mRetrogradeMotionReported) { Loading @@ -2541,9 +2566,21 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } else { mRetrogradeMotionReported = false; } if (deltaPosition < MINIMUM_POSITION_DELTA) { timestamp = mPreviousTimestamp; // Use last valid timestamp. if (deltaPosition < 0) { timestamp.mPosition = mPreviousTimestamp.mPosition; deltaPosition = 0; } #if 0 // Uncomment this to verify audio timestamp rate. const int64_t deltaTime = convertTimespecToNs(timestamp.mTime) - previousTimeNanos; if (deltaTime != 0) { const int64_t computedSampleRate = deltaPosition * (long long)NANOS_PER_SECOND / deltaTime; ALOGD("computedSampleRate:%u sampleRate:%u", (unsigned)computedSampleRate, mSampleRate); } #endif } mPreviousTimestamp = timestamp; mPreviousTimestampValid = true; Loading
media/libmediaplayerservice/MediaPlayerService.cpp +13 −25 Original line number Diff line number Diff line Loading @@ -1521,57 +1521,45 @@ int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) c } uint32_t numFramesPlayed; int64_t numFramesPlayedAt; int64_t numFramesPlayedAtUs; AudioTimestamp ts; static const int64_t kStaleTimestamp100ms = 100000; status_t res = mTrack->getTimestamp(ts); if (res == OK) { // case 1: mixing audio tracks and offloaded tracks. numFramesPlayed = ts.mPosition; numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; const int64_t timestampAge = nowUs - numFramesPlayedAt; if (timestampAge > kStaleTimestamp100ms) { // This is an audio FIXME. // getTimestamp returns a timestamp which may come from audio mixing threads. // After pausing, the MixerThread may go idle, thus the mTime estimate may // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms, // the max latency should be about 25ms with an average around 12ms (to be verified). // For safety we use 100ms. ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)", (long long)nowUs, (long long)numFramesPlayedAt); numFramesPlayedAt = nowUs - kStaleTimestamp100ms; } //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track numFramesPlayed = 0; numFramesPlayedAt = nowUs; numFramesPlayedAtUs = nowUs; //ALOGD("getTimestamp: WOULD_BLOCK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else { // case 3: transitory at new track or audio fast tracks. res = mTrack->getPosition(&numFramesPlayed); CHECK_EQ(res, (status_t)OK); numFramesPlayedAt = nowUs; numFramesPlayedAt += 1000LL * mTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = nowUs; numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours. int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz) + nowUs - numFramesPlayedAt; + nowUs - numFramesPlayedAtUs; if (durationUs < 0) { // Occurs when numFramesPlayed position is very small and the following: // (1) In case 1, the time nowUs is computed before getTimestamp() is called and // numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed. // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed. // (2) In case 3, using getPosition and adding mAudioSink->latency() to // numFramesPlayedAt, by a time amount greater than numFramesPlayed. // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed. // // Both of these are transitory conditions. ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs); durationUs = 0; } ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)", (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt); (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAtUs); return durationUs; } Loading
media/libstagefright/MediaSync.cpp +12 −28 Original line number Diff line number Diff line Loading @@ -478,59 +478,43 @@ int64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) { CHECK(mAudioTrack != NULL); uint32_t numFramesPlayed; int64_t numFramesPlayedAt; int64_t numFramesPlayedAtUs; AudioTimestamp ts; static const int64_t kStaleTimestamp100ms = 100000; status_t res = mAudioTrack->getTimestamp(ts); if (res == OK) { // case 1: mixing audio tracks. numFramesPlayed = ts.mPosition; numFramesPlayedAt = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; const int64_t timestampAge = nowUs - numFramesPlayedAt; if (timestampAge > kStaleTimestamp100ms) { // This is an audio FIXME. // getTimestamp returns a timestamp which may come from audio // mixing threads. After pausing, the MixerThread may go idle, // thus the mTime estimate may become stale. Assuming that the // MixerThread runs 20ms, with FastMixer at 5ms, the max latency // should be about 25ms with an average around 12ms (to be // verified). For safety we use 100ms. ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) " "numFramesPlayedAt(%lld)", (long long)nowUs, (long long)numFramesPlayedAt); numFramesPlayedAt = nowUs - kStaleTimestamp100ms; } numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; //ALOGD("getTimestamp: OK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track numFramesPlayed = 0; numFramesPlayedAt = nowUs; numFramesPlayedAtUs = nowUs; //ALOGD("getTimestamp: WOULD_BLOCK %d %lld", // numFramesPlayed, (long long)numFramesPlayedAt); // numFramesPlayed, (long long)numFramesPlayedAtUs); } else { // case 3: transitory at new track or audio fast tracks. res = mAudioTrack->getPosition(&numFramesPlayed); CHECK_EQ(res, (status_t)OK); numFramesPlayedAt = nowUs; numFramesPlayedAt += 1000LL * mAudioTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAt); numFramesPlayedAtUs = nowUs; numFramesPlayedAtUs += 1000LL * mAudioTrack->latency() / 2; /* XXX */ //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs); } //can't be negative until 12.4 hrs, test. //CHECK_EQ(numFramesPlayed & (1 << 31), 0); int64_t durationUs = getDurationIfPlayedAtNativeSampleRate_l(numFramesPlayed) + nowUs - numFramesPlayedAt; + nowUs - numFramesPlayedAtUs; if (durationUs < 0) { // Occurs when numFramesPlayed position is very small and the following: // (1) In case 1, the time nowUs is computed before getTimestamp() is // called and numFramesPlayedAt is greater than nowUs by time more // called and numFramesPlayedAtUs is greater than nowUs by time more // than numFramesPlayed. // (2) In case 3, using getPosition and adding mAudioTrack->latency() // to numFramesPlayedAt, by a time amount greater than // to numFramesPlayedAtUs, by a time amount greater than // numFramesPlayed. // // Both of these are transitory conditions. Loading @@ -541,7 +525,7 @@ int64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) { ALOGV("getPlayedOutAudioDurationMedia_l(%lld) nowUs(%lld) frames(%u) " "framesAt(%lld)", (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt); (long long)numFramesPlayedAtUs); return durationUs; } Loading