diff options
| -rw-r--r-- | include/media/AudioParameter.h | 12 | ||||
| -rw-r--r-- | include/media/AudioTrack.h | 8 | ||||
| -rw-r--r-- | include/media/MediaPlayerInterface.h | 5 | ||||
| -rwxr-xr-x | libvideoeditor/lvpp/VideoEditorPlayer.cpp | 11 | ||||
| -rwxr-xr-x | libvideoeditor/lvpp/VideoEditorPlayer.h | 5 | ||||
| -rw-r--r-- | media/libmedia/AudioParameter.cpp | 14 | ||||
| -rw-r--r-- | media/libmedia/AudioTrack.cpp | 23 | ||||
| -rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 25 | ||||
| -rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 11 | ||||
| -rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 36 | ||||
| -rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.h | 3 | ||||
| -rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 4 | ||||
| -rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 80 | ||||
| -rw-r--r-- | services/audioflinger/AudioFlinger.h | 40 |
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); |
