summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioParameter.h12
-rw-r--r--include/media/AudioTrack.h8
-rw-r--r--include/media/MediaPlayerInterface.h5
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorPlayer.cpp11
-rwxr-xr-xlibvideoeditor/lvpp/VideoEditorPlayer.h5
-rw-r--r--media/libmedia/AudioParameter.cpp14
-rw-r--r--media/libmedia/AudioTrack.cpp23
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp25
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h11
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp36
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp4
-rw-r--r--services/audioflinger/AudioFlinger.cpp80
-rw-r--r--services/audioflinger/AudioFlinger.h40
14 files changed, 213 insertions, 64 deletions
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
index 79d5d82..8cb2fa7 100644
--- a/include/media/AudioParameter.h
+++ b/include/media/AudioParameter.h
@@ -40,12 +40,12 @@ public:
// keyFrameCount: to change audio output frame count, value is an int
// keyInputSource: to change audio input source, value is an int in audio_source_t
// (defined in media/mediarecorder.h)
- static const char *keyRouting;
- static const char *keySamplingRate;
- static const char *keyFormat;
- static const char *keyChannels;
- static const char *keyFrameCount;
- static const char *keyInputSource;
+ static const char * const keyRouting;
+ static const char * const keySamplingRate;
+ static const char * const keyFormat;
+ static const char * const keyChannels;
+ static const char * const keyFrameCount;
+ static const char * const keyInputSource;
String8 toString();
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7d5d772..6de6486 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -139,13 +139,15 @@ public:
* latency of the track. The actual size selected by the AudioTrack could be
* larger if the requested size is not compatible with current audio HAL
* latency.
- * flags: Reserved for future use.
+ * flags: See comments on audio_policy_output_flags_t in <system/audio_policy.h>.
* cbf: Callback function. If not null, this function is called periodically
* to request new PCM data.
* user: Context for use by the callback receiver.
* notificationFrames: The callback function is called each time notificationFrames PCM
* frames have been consumed from track input buffer.
* sessionId: Specific session ID, or zero to use default.
+ * threadCanCallJava: Whether callbacks are made from an attached thread and thus can call JNI.
+ * If not present in parameter list, then fixed at false.
*/
AudioTrack( audio_stream_type_t streamType,
@@ -157,7 +159,7 @@ public:
callback_t cbf = NULL,
void* user = NULL,
int notificationFrames = 0,
- int sessionId = 0);
+ int sessionId = 0);
// DEPRECATED
explicit AudioTrack( int streamType,
@@ -189,7 +191,7 @@ public:
callback_t cbf = NULL,
void* user = NULL,
int notificationFrames = 0,
- int sessionId = 0);
+ int sessionId = 0);
/* Terminates the AudioTrack and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioTrack.
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index d4aa233..9a8f4b0 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -87,8 +87,9 @@ 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;
- virtual int getSessionId() = 0;
+ virtual status_t getPosition(uint32_t *position) const = 0;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0;
+ virtual int getSessionId() const = 0;
// If no callback is specified, use the "write" API below to submit
// audio data.
diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.cpp b/libvideoeditor/lvpp/VideoEditorPlayer.cpp
index 57cab08..1ba1f44 100755
--- a/libvideoeditor/lvpp/VideoEditorPlayer.cpp
+++ b/libvideoeditor/lvpp/VideoEditorPlayer.cpp
@@ -376,12 +376,19 @@ float VideoEditorPlayer::VeAudioOutput::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t VideoEditorPlayer::VeAudioOutput::getPosition(uint32_t *position) {
+status_t VideoEditorPlayer::VeAudioOutput::getPosition(uint32_t *position) const {
if (mTrack == 0) return NO_INIT;
return mTrack->getPosition(position);
}
+status_t VideoEditorPlayer::VeAudioOutput::getFramesWritten(uint32_t *written) const {
+
+ if (mTrack == 0) return NO_INIT;
+ *written = mNumFramesWritten;
+ return OK;
+}
+
status_t VideoEditorPlayer::VeAudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
@@ -569,7 +576,7 @@ status_t VideoEditorPlayer::VeAudioOutput::dump(int fd, const Vector<String16>&
return NO_ERROR;
}
-int VideoEditorPlayer::VeAudioOutput::getSessionId() {
+int VideoEditorPlayer::VeAudioOutput::getSessionId() const {
return mSessionId;
}
diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.h b/libvideoeditor/lvpp/VideoEditorPlayer.h
index 6962501..350b384 100755
--- a/libvideoeditor/lvpp/VideoEditorPlayer.h
+++ b/libvideoeditor/lvpp/VideoEditorPlayer.h
@@ -45,8 +45,9 @@ class VideoEditorPlayer : public MediaPlayerInterface {
virtual ssize_t frameSize() const;
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t getPosition(uint32_t *position);
- virtual int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t*) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index abc7b3f..9766ee6 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -19,16 +19,18 @@
#include <utils/Log.h>
+#include <hardware/audio.h>
#include <media/AudioParameter.h>
namespace android {
-const char *AudioParameter::keyRouting = "routing";
-const char *AudioParameter::keySamplingRate = "sampling_rate";
-const char *AudioParameter::keyFormat = "format";
-const char *AudioParameter::keyChannels = "channels";
-const char *AudioParameter::keyFrameCount = "frame_count";
-const char *AudioParameter::keyInputSource = "input_source";
+// static
+const char * const AudioParameter::keyRouting = AUDIO_PARAMETER_STREAM_ROUTING;
+const char * const AudioParameter::keySamplingRate = AUDIO_PARAMETER_STREAM_SAMPLING_RATE;
+const char * const AudioParameter::keyFormat = AUDIO_PARAMETER_STREAM_FORMAT;
+const char * const AudioParameter::keyChannels = AUDIO_PARAMETER_STREAM_CHANNELS;
+const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
+const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
AudioParameter::AudioParameter(const String8& keyValuePairs)
{
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d73eabd..c619ad7 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -226,7 +226,8 @@ status_t AudioTrack::set(
// force direct flag if format is not linear PCM
if (!audio_is_linear_pcm(format)) {
- flags = (audio_policy_output_flags_t) (flags | AUDIO_POLICY_OUTPUT_FLAG_DIRECT);
+ flags = (audio_policy_output_flags_t)
+ ((flags | AUDIO_POLICY_OUTPUT_FLAG_DIRECT) & ~AUDIO_POLICY_OUTPUT_FLAG_FAST);
}
if (!audio_is_output_channel(channelMask)) {
@@ -252,6 +253,7 @@ status_t AudioTrack::set(
mNotificationFramesReq = notificationFrames;
mSessionId = sessionId;
mAuxEffectId = 0;
+ mCbf = cbf;
// create the IAudioTrack
status_t status = createTrack_l(streamType,
@@ -280,7 +282,6 @@ status_t AudioTrack::set(
mSharedBuffer = sharedBuffer;
mMuted = false;
mActive = false;
- mCbf = cbf;
mUserData = user;
mLoopCount = 0;
mMarkerPosition = 0;
@@ -762,6 +763,18 @@ status_t AudioTrack::createTrack_l(
return NO_INIT;
}
+ // Client decides whether the track is TIMED (see below), but can only express a preference
+ // for FAST. Server will perform additional tests.
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_FAST) && !(
+ // either of these use cases:
+ // use case 1: shared buffer
+ (sharedBuffer != 0) ||
+ // use case 2: callback handler
+ (mCbf != NULL))) {
+ ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
+ flags = (audio_policy_output_flags_t) (flags & ~AUDIO_POLICY_OUTPUT_FLAG_FAST);
+ }
+
mNotificationFramesAct = mNotificationFramesReq;
if (!audio_is_linear_pcm(format)) {
if (sharedBuffer != 0) {
@@ -786,7 +799,7 @@ status_t AudioTrack::createTrack_l(
if (mNotificationFramesAct > (uint32_t)frameCount/2) {
mNotificationFramesAct = frameCount/2;
}
- if (frameCount < minFrameCount) {
+ if (frameCount < minFrameCount && !(flags & AUDIO_POLICY_OUTPUT_FLAG_FAST)) {
// not ALOGW because it happens all the time when playing key clicks over A2DP
ALOGV("Minimum buffer size corrected from %d to %d",
frameCount, minFrameCount);
@@ -807,6 +820,10 @@ status_t AudioTrack::createTrack_l(
if (mIsTimed) {
trackFlags |= IAudioFlinger::TRACK_TIMED;
}
+ if (flags & AUDIO_POLICY_OUTPUT_FLAG_FAST) {
+ trackFlags |= IAudioFlinger::TRACK_FAST;
+ }
+
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
streamType,
sampleRate,
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cc3138d..a977337 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1417,6 +1417,7 @@ MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
: mCallback(NULL),
mCallbackCookie(NULL),
mCallbackData(NULL),
+ mBytesWritten(0),
mSessionId(sessionId) {
ALOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
@@ -1495,12 +1496,19 @@ float MediaPlayerService::AudioOutput::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
{
if (mTrack == 0) return NO_INIT;
return mTrack->getPosition(position);
}
+status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
+{
+ if (mTrack == 0) return NO_INIT;
+ *frameswritten = mBytesWritten / frameSize();
+ return OK;
+}
+
status_t MediaPlayerService::AudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format, int bufferCount,
@@ -1656,6 +1664,7 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() {
mTrack = NULL;
mNextOutput->mSampleRateHz = mSampleRateHz;
mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
+ mNextOutput->mBytesWritten = mBytesWritten;
}
}
@@ -1666,6 +1675,7 @@ ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
//ALOGV("write(%p, %u)", buffer, size);
if (mTrack) {
ssize_t ret = mTrack->write(buffer, size);
+ mBytesWritten += ret;
return ret;
}
return NO_INIT;
@@ -1777,7 +1787,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
data->unlock();
}
-int MediaPlayerService::AudioOutput::getSessionId()
+int MediaPlayerService::AudioOutput::getSessionId() const
{
return mSessionId;
}
@@ -1802,13 +1812,20 @@ float MediaPlayerService::AudioCache::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
{
if (position == 0) return BAD_VALUE;
*position = mSize;
return NO_ERROR;
}
+status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
+{
+ if (written == 0) return BAD_VALUE;
+ *written = mSize;
+ return NO_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////
struct CallbackThread : public Thread {
@@ -1971,7 +1988,7 @@ void MediaPlayerService::AudioCache::notify(
p->mSignal.signal();
}
-int MediaPlayerService::AudioCache::getSessionId()
+int MediaPlayerService::AudioCache::getSessionId() const
{
return 0;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index b08dd6c..2a8cfd2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -84,8 +84,9 @@ 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 int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
@@ -122,6 +123,7 @@ class MediaPlayerService : public BnMediaPlayerService
AudioCallback mCallback;
void * mCallbackCookie;
CallbackData * mCallbackData;
+ uint64_t mBytesWritten;
audio_stream_type_t mStreamType;
float mLeftVolume;
float mRightVolume;
@@ -181,8 +183,9 @@ class MediaPlayerService : public BnMediaPlayerService
virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AUDIO_FORMAT_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 int getSessionId();
+ virtual status_t getPosition(uint32_t *position) const;
+ virtual status_t getFramesWritten(uint32_t *frameswritten) const;
+ virtual int getSessionId() const;
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 544d501..11cea3b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -39,6 +39,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/SkipCutBuffer.h>
#include <gui/ISurfaceTexture.h>
#include "avc_utils.h"
@@ -63,10 +64,13 @@ NuPlayer::NuPlayer()
mSkipRenderingVideoUntilMediaTimeUs(-1ll),
mVideoLateByUs(0ll),
mNumFramesTotal(0ll),
- mNumFramesDropped(0ll) {
+ mNumFramesDropped(0ll),
+ mSkipCutBuffer(NULL) {
}
NuPlayer::~NuPlayer() {
+ delete mSkipCutBuffer;
+ mSkipCutBuffer = NULL;
}
void NuPlayer::setUID(uid_t uid) {
@@ -234,6 +238,32 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mSource->start();
+ sp<MetaData> meta = mSource->getFormat(true /* audio */);
+ if (meta != NULL) {
+ int32_t delay = 0;
+ if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
+ delay = 0;
+ }
+ int32_t padding = 0;
+ if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
+ padding = 0;
+ }
+ int32_t numchannels = 0;
+ if (delay + padding) {
+ if (meta->findInt32(kKeyChannelCount, &numchannels)) {
+ size_t frameSize = numchannels * sizeof(int16_t);
+ if (mSkipCutBuffer) {
+ size_t prevbuffersize = mSkipCutBuffer->size();
+ if (prevbuffersize != 0) {
+ ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
+ }
+ delete mSkipCutBuffer;
+ }
+ mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
+ }
+ }
+ }
+
mRenderer = new Renderer(
mAudioSink,
new AMessage(kWhatRendererNotify, id()));
@@ -844,6 +874,10 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
skipUntilMediaTimeUs = -1;
}
+ if (audio && mSkipCutBuffer) {
+ mSkipCutBuffer->submit(buffer);
+ }
+
mRenderer->queueBuffer(audio, buffer, reply);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 25766e0..f917f64 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -27,6 +27,7 @@ namespace android {
struct ACodec;
struct MetaData;
struct NuPlayerDriver;
+class SkipCutBuffer;
struct NuPlayer : public AHandler {
NuPlayer();
@@ -128,6 +129,8 @@ private:
int64_t mVideoLateByUs;
int64_t mNumFramesTotal, mNumFramesDropped;
+ SkipCutBuffer *mSkipCutBuffer;
+
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index ecbc428..1f13955 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -591,6 +591,10 @@ bool NuPlayer::Renderer::dropBufferWhileFlushing(
void NuPlayer::Renderer::onAudioSinkChanged() {
CHECK(!mDrainAudioQueuePending);
mNumFramesWritten = 0;
+ uint32_t written;
+ if (mAudioSink->getFramesWritten(&written) == OK) {
+ mNumFramesWritten = written;
+ }
}
void NuPlayer::Renderer::notifyPosition() {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 83af5f3..ad386f6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -504,7 +504,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
track = thread->createTrack_l(client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, lSessionId, isTimed, &lStatus);
+ channelMask, frameCount, sharedBuffer, lSessionId, flags, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
@@ -1608,12 +1608,50 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
int frameCount,
const sp<IMemory>& sharedBuffer,
int sessionId,
- bool isTimed,
+ IAudioFlinger::track_flags_t flags,
status_t *status)
{
sp<Track> track;
status_t lStatus;
+ bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
+
+ // client expresses a preference for FAST, but we get the final say
+ if ((flags & IAudioFlinger::TRACK_FAST) &&
+ !(
+ // not timed
+ (!isTimed) &&
+ // either of these use cases:
+ (
+ // use case 1: shared buffer with any frame count
+ (
+ (sharedBuffer != 0)
+ ) ||
+ // use case 2: callback handler and small power-of-2 frame count
+ (
+ // unfortunately we can't verify that there's a callback until start()
+ // FIXME supported frame counts should not be hard-coded
+ (
+ (frameCount == 128) ||
+ (frameCount == 256) ||
+ (frameCount == 512)
+ )
+ )
+ ) &&
+ // PCM data
+ audio_is_linear_pcm(format) &&
+ // mono or stereo
+ ( (channelMask == AUDIO_CHANNEL_OUT_MONO) ||
+ (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) &&
+ // hardware sample rate
+ (sampleRate == mSampleRate)
+ // FIXME test that MixerThread for this fast track has a capable output HAL
+ // FIXME add a permission test also?
+ ) ) {
+ ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
+ flags &= ~IAudioFlinger::TRACK_FAST;
+ }
+
if (mType == DIRECT) {
if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
@@ -1661,7 +1699,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
if (!isTimed) {
track = new Track(this, client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, sessionId);
+ channelMask, frameCount, sharedBuffer, sessionId, flags);
} else {
track = TimedTrack::create(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId);
@@ -1924,7 +1962,7 @@ AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::PlaybackThread::stream()
+audio_stream_t* AudioFlinger::PlaybackThread::stream() const
{
if (mOutput == NULL) {
return NULL;
@@ -1932,7 +1970,7 @@ audio_stream_t* AudioFlinger::PlaybackThread::stream()
return &mOutput->stream->common;
}
-uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
+uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
{
// A2DP output latency is not due only to buffering capacity. It also reflects encoding,
// decoding and transfer time. So sleeping for half of the latency would likely cause
@@ -2817,12 +2855,12 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>
return NO_ERROR;
}
-uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
{
return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
}
-uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
+uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
{
return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
}
@@ -3166,7 +3204,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
return reconfig;
}
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
{
uint32_t time;
if (audio_is_linear_pcm(mFormat)) {
@@ -3177,7 +3215,7 @@ uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
{
uint32_t time;
if (audio_is_linear_pcm(mFormat)) {
@@ -3188,7 +3226,7 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
+uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
{
uint32_t time;
if (audio_is_linear_pcm(mFormat)) {
@@ -3351,7 +3389,7 @@ bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<Output
return true;
}
-uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
+uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
{
return (mWaitTimeMs * 1000) / 2;
}
@@ -3550,7 +3588,8 @@ AudioFlinger::PlaybackThread::Track::Track(
uint32_t channelMask,
int frameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId)
+ int sessionId,
+ IAudioFlinger::track_flags_t flags)
: TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
mMute(false),
// mFillingUpStatus ?
@@ -3561,7 +3600,8 @@ AudioFlinger::PlaybackThread::Track::Track(
mMainBuffer(thread->mixBuffer()),
mAuxBuffer(NULL),
mAuxEffectId(0), mHasVolumeController(false),
- mPresentationCompleteFrames(0)
+ mPresentationCompleteFrames(0),
+ mFlags(flags)
{
if (mCblk != NULL) {
// NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
@@ -3707,6 +3747,13 @@ status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid,
status_t status = NO_ERROR;
ALOGV("start(%d), calling pid %d session %d tid %d",
mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
+ // check for use case 2 with missing callback
+ if (isFastTrack() && (mSharedBuffer == 0) && (tid == 0)) {
+ ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
+ mFlags &= ~IAudioFlinger::TRACK_FAST;
+ // FIXME the track must be invalidated and moved to another thread or
+ // attached directly to the normal mixer now
+ }
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
@@ -3922,7 +3969,7 @@ AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
const sp<IMemory>& sharedBuffer,
int sessionId)
: Track(thread, client, streamType, sampleRate, format, channelMask,
- frameCount, sharedBuffer, sessionId),
+ frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
mTimedSilenceBuffer(NULL),
mTimedSilenceBufferSize(0),
mTimedAudioOutputOnTime(false),
@@ -4400,7 +4447,8 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
audio_format_t format,
uint32_t channelMask,
int frameCount)
- : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
+ : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
+ NULL, 0, IAudioFlinger::TRACK_DEFAULT),
mActive(false), mSourceThread(sourceThread)
{
@@ -5623,7 +5671,7 @@ AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::RecordThread::stream()
+audio_stream_t* AudioFlinger::RecordThread::stream() const
{
if (mInput == NULL) {
return NULL;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2376aff..de59f6d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -472,7 +472,7 @@ private:
audio_io_handle_t id() const { return mId;}
bool standby() const { return mStandby; }
uint32_t device() const { return mDevice; }
- virtual audio_stream_t* stream() = 0;
+ virtual audio_stream_t* stream() const = 0;
sp<EffectHandle> createEffect_l(
const sp<AudioFlinger::Client>& client,
@@ -662,7 +662,8 @@ private:
uint32_t channelMask,
int frameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId);
+ int sessionId,
+ IAudioFlinger::track_flags_t flags);
virtual ~Track();
void dump(char* buffer, size_t size);
@@ -689,6 +690,9 @@ private:
int16_t *mainBuffer() const { return mMainBuffer; }
int auxEffectId() const { return mAuxEffectId; }
+ bool isFastTrack() const
+ { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; }
+
protected:
// for numerous
friend class PlaybackThread;
@@ -742,6 +746,8 @@ private:
bool mHasVolumeController;
size_t mPresentationCompleteFrames; // number of frames written to the audio HAL
// when this track will be fully rendered
+ private:
+ IAudioFlinger::track_flags_t mFlags;
}; // end of Track
class TimedTrack : public Track {
@@ -913,12 +919,12 @@ public:
int frameCount,
const sp<IMemory>& sharedBuffer,
int sessionId,
- bool isTimed,
+ IAudioFlinger::track_flags_t flags,
status_t *status);
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
- virtual audio_stream_t* stream();
+ virtual audio_stream_t* stream() const;
void suspend() { mSuspended++; }
void restore() { if (mSuspended > 0) mSuspended--; }
@@ -960,9 +966,13 @@ public:
// Allocate a track name. Returns name >= 0 if successful, -1 on failure.
virtual int getTrackName_l() = 0;
virtual void deleteTrackName_l(int name) = 0;
- virtual uint32_t activeSleepTimeUs();
- virtual uint32_t idleSleepTimeUs() = 0;
- virtual uint32_t suspendSleepTimeUs() = 0;
+
+ // Time to sleep between cycles when:
+ virtual uint32_t activeSleepTimeUs() const; // mixer state MIXER_TRACKS_ENABLED
+ virtual uint32_t idleSleepTimeUs() const = 0; // mixer state MIXER_IDLE
+ virtual uint32_t suspendSleepTimeUs() const = 0; // audio policy manager suspended us
+ // No sleep when mixer state == MIXER_TRACKS_READY; relies on audio HAL stream->write()
+ // No sleep in standby mode; waits on a condition
// Code snippets that are temporarily lifted up out of threadLoop() until the merge
void checkSilentMode_l();
@@ -1048,8 +1058,8 @@ public:
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
virtual int getTrackName_l();
virtual void deleteTrackName_l(int name);
- virtual uint32_t idleSleepTimeUs();
- virtual uint32_t suspendSleepTimeUs();
+ virtual uint32_t idleSleepTimeUs() const;
+ virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
// threadLoop snippets
@@ -1073,9 +1083,9 @@ public:
protected:
virtual int getTrackName_l();
virtual void deleteTrackName_l(int name);
- virtual uint32_t activeSleepTimeUs();
- virtual uint32_t idleSleepTimeUs();
- virtual uint32_t suspendSleepTimeUs();
+ virtual uint32_t activeSleepTimeUs() const;
+ virtual uint32_t idleSleepTimeUs() const;
+ virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
// threadLoop snippets
@@ -1110,9 +1120,9 @@ private:
// Thread virtuals
void addOutputTrack(MixerThread* thread);
void removeOutputTrack(MixerThread* thread);
- uint32_t waitTimeMs() { return mWaitTimeMs; }
+ uint32_t waitTimeMs() const { return mWaitTimeMs; }
protected:
- virtual uint32_t activeSleepTimeUs();
+ virtual uint32_t activeSleepTimeUs() const;
private:
bool outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
@@ -1260,7 +1270,7 @@ private:
status_t dump(int fd, const Vector<String16>& args);
AudioStreamIn* getInput() const;
AudioStreamIn* clearInput();
- virtual audio_stream_t* stream();
+ virtual audio_stream_t* stream() const;
// AudioBufferProvider interface
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts);