Merge "Add the ability to query the amount of cached data to NuMediaExtractor."
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index d52ed42..4667649 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -64,7 +64,7 @@
LOCAL_SRC_FILES += FastMixer.cpp FastMixerState.cpp
-#LOCAL_CFLAGS += -DFAST_MIXER_STATISTICS
+LOCAL_CFLAGS += -DFAST_MIXER_STATISTICS
LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 99dcf45..bce30d7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3994,20 +3994,38 @@
size_t trimEnd;
for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
- int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
- / mCblk->frameSize;
int64_t bufEnd;
- if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
- &bufEnd)) {
- ALOGE("Failed to convert frame count of %lld to media time duration"
- " (scale factor %d/%u) in %s", frameCount,
- mMediaTimeToSampleTransform.a_to_b_numer,
- mMediaTimeToSampleTransform.a_to_b_denom,
- __PRETTY_FUNCTION__);
- break;
+ if ((trimEnd + 1) < mTimedBufferQueue.size()) {
+ // We have a next buffer. Just use its PTS as the PTS of the frame
+ // following the last frame in this buffer. If the stream is sparse
+ // (ie, there are deliberate gaps left in the stream which should be
+ // filled with silence by the TimedAudioTrack), then this can result
+ // in one extra buffer being left un-trimmed when it could have
+ // been. In general, this is not typical, and we would rather
+ // optimized away the TS calculation below for the more common case
+ // where PTSes are contiguous.
+ bufEnd = mTimedBufferQueue[trimEnd + 1].pts();
+ } else {
+ // We have no next buffer. Compute the PTS of the frame following
+ // the last frame in this buffer by computing the duration of of
+ // this frame in media time units and adding it to the PTS of the
+ // buffer.
+ int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
+ / mCblk->frameSize;
+
+ if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
+ &bufEnd)) {
+ ALOGE("Failed to convert frame count of %lld to media time"
+ " duration" " (scale factor %d/%u) in %s",
+ frameCount,
+ mMediaTimeToSampleTransform.a_to_b_numer,
+ mMediaTimeToSampleTransform.a_to_b_denom,
+ __PRETTY_FUNCTION__);
+ break;
+ }
+ bufEnd += mTimedBufferQueue[trimEnd].pts();
}
- bufEnd += mTimedBufferQueue[trimEnd].pts();
if (bufEnd > mediaTimeNow)
break;
@@ -4111,6 +4129,7 @@
if (pts == AudioBufferProvider::kInvalidPTS) {
buffer->raw = 0;
buffer->frameCount = 0;
+ mTimedAudioOutputOnTime = false;
return INVALID_OPERATION;
}
@@ -4203,14 +4222,14 @@
// the current output position is within this threshold, then we will
// concatenate the next input samples to the previous output
const int64_t kSampleContinuityThreshold =
- (static_cast<int64_t>(sampleRate()) << 32) / 10;
+ (static_cast<int64_t>(sampleRate()) << 32) / 250;
// if this is the first buffer of audio that we're emitting from this track
// then it should be almost exactly on time.
const int64_t kSampleStartupThreshold = 1LL << 32;
if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
- (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
+ (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
// the next input is close enough to being on time, so concatenate it
// with the last output
timedYieldSamples_l(buffer);
@@ -4218,7 +4237,13 @@
ALOGVV("*** on time: head.pos=%d frameCount=%u",
head.position(), buffer->frameCount);
return NO_ERROR;
- } else if (sampleDelta > 0) {
+ }
+
+ // Looks like our output is not on time. Reset our on timed status.
+ // Next time we mix samples from our input queue, then should be within
+ // the StartupThreshold.
+ mTimedAudioOutputOnTime = false;
+ if (sampleDelta > 0) {
// the gap between the current output position and the proper start of
// the next input sample is too big, so fill it with silence
uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 14954f7..841b06a 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -130,6 +130,7 @@
continue;
case FastMixerState::COLD_IDLE:
// only perform a cold idle command once
+ // FIXME consider checking previous state and only perform if previous != COLD_IDLE
if (current->mColdGen != coldGen) {
int32_t *coldFutexAddr = current->mColdFutexAddr;
ALOG_ASSERT(coldFutexAddr != NULL);
@@ -176,6 +177,7 @@
sampleRate = Format_sampleRate(format);
ALOG_ASSERT(Format_channelCount(format) == 2);
}
+ dumpState->mSampleRate = sampleRate;
}
if ((format != previousFormat) || (frameCount != previous->mFrameCount)) {
@@ -207,6 +209,7 @@
// we need to reconfigure all active tracks
previousTrackMask = 0;
fastTracksGen = current->mFastTracksGen - 1;
+ dumpState->mFrameCount = frameCount;
} else {
previousTrackMask = previous->mTrackMask;
}
@@ -251,6 +254,12 @@
mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
(void *) mixBuffer);
// newly allocated track names default to full scale volume
+ if (fastTrack->mSampleRate != 0 && fastTrack->mSampleRate != sampleRate) {
+ mixer->setParameter(name, AudioMixer::RESAMPLE,
+ AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate);
+ }
+ mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
+ (void *) fastTrack->mChannelMask);
mixer->enable(name);
}
generations[i] = fastTrack->mGeneration;
@@ -276,6 +285,16 @@
mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1,
(void *)0x1000);
}
+ if (fastTrack->mSampleRate != 0 &&
+ fastTrack->mSampleRate != sampleRate) {
+ mixer->setParameter(name, AudioMixer::RESAMPLE,
+ AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate);
+ } else {
+ mixer->setParameter(name, AudioMixer::RESAMPLE,
+ AudioMixer::REMOVE, NULL);
+ }
+ mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
+ (void *) fastTrack->mChannelMask);
// already enabled
}
generations[i] = fastTrack->mGeneration;
@@ -401,7 +420,8 @@
FastMixerDumpState::FastMixerDumpState() :
mCommand(FastMixerState::INITIAL), mWriteSequence(0), mFramesWritten(0),
- mNumTracks(0), mWriteErrors(0), mUnderruns(0), mOverruns(0)
+ mNumTracks(0), mWriteErrors(0), mUnderruns(0), mOverruns(0),
+ mSampleRate(0), mFrameCount(0)
#ifdef FAST_MIXER_STATISTICS
, mMean(0.0), mMinimum(0.0), mMaximum(0.0), mStddev(0.0)
#endif
@@ -443,9 +463,11 @@
break;
}
fdprintf(fd, "FastMixer command=%s writeSequence=%u framesWritten=%u\n"
- " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n",
+ " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
+ " sampleRate=%u frameCount=%u\n",
string, mWriteSequence, mFramesWritten,
- mNumTracks, mWriteErrors, mUnderruns, mOverruns);
+ mNumTracks, mWriteErrors, mUnderruns, mOverruns,
+ mSampleRate, mFrameCount);
#ifdef FAST_MIXER_STATISTICS
fdprintf(fd, " cycle time in ms: mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
mMean*1e3, mMinimum*1e3, mMaximum*1e3, mStddev*1e3);
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index b24f2eb..8a8fcb8 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -58,6 +58,8 @@
uint32_t mWriteErrors; // total number of write() errors
uint32_t mUnderruns; // total number of underruns
uint32_t mOverruns; // total number of overruns
+ uint32_t mSampleRate;
+ size_t mFrameCount;
#ifdef FAST_MIXER_STATISTICS
// cycle times in seconds
float mMean;
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/FastMixerState.cpp
index 4eacacf..139a1c8 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/FastMixerState.cpp
@@ -19,7 +19,8 @@
namespace android {
FastTrack::FastTrack() :
- mBufferProvider(NULL), mVolumeProvider(NULL), mGeneration(0)
+ mBufferProvider(NULL), mVolumeProvider(NULL), mSampleRate(0),
+ mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mGeneration(0)
{
}
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h
index 64171ac..83094c8 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/FastMixerState.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H
#define ANDROID_AUDIO_FAST_MIXER_STATE_H
+#include <system/audio.h>
#include "AudioBufferProvider.h"
#include "NBAIO.h"
@@ -41,6 +42,8 @@
AudioBufferProvider* mBufferProvider; // must not be NULL
VolumeProvider* mVolumeProvider; // optional; if NULL then full-scale
+ unsigned mSampleRate; // optional; if zero then use mixer sample rate
+ audio_channel_mask_t mChannelMask; // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
int mGeneration; // increment when any field is assigned
};