From faeb0f291330134dc4468359a36e099aae508449 Mon Sep 17 00:00:00 2001 From: Ronghua Wu Date: Thu, 21 May 2015 12:20:21 -0700 Subject: libmediaplayerservice: try to open audio sink in offload mode in error. Bug: 19061432 Bug: 21370108 Change-Id: Iaa757555ef37fd1ac87b6e2d5a9969bb58cc5ebc --- include/media/AudioTrack.h | 15 ++++++++--- include/media/MediaPlayerInterface.h | 3 ++- media/libmedia/AudioTrack.cpp | 16 ++++++----- media/libmediaplayerservice/MediaPlayerService.cpp | 9 ++++--- media/libmediaplayerservice/MediaPlayerService.h | 3 ++- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 21 ++++++++++++--- .../nuplayer/NuPlayerDecoder.cpp | 1 + .../nuplayer/NuPlayerRenderer.cpp | 31 +++++++++++----------- .../nuplayer/NuPlayerRenderer.h | 20 +++++++------- 9 files changed, 76 insertions(+), 43 deletions(-) diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 458f4b4..e9f0131 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -183,6 +183,10 @@ public: * pid: Process ID of the app which initially requested this AudioTrack * for power management tracking, or -1 for current process ID. * pAttributes: If not NULL, supersedes streamType for use case selection. + * doNotReconnect: If set to true, AudioTrack won't automatically recreate the IAudioTrack + binder to AudioFlinger. + It will return an error instead. The application will recreate + the track based on offloading or different channel configuration, etc. * threadCanCallJava: Not present in parameter list, and so is fixed at false. */ @@ -200,7 +204,8 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Creates an audio track and registers it with AudioFlinger. * With this constructor, the track is configured for static buffer mode. @@ -228,7 +233,8 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources associated with the AudioTrack. @@ -272,7 +278,8 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Result of constructing the AudioTrack. This must be checked for successful initialization * before using any AudioTrack API (except for set()), because using @@ -877,6 +884,8 @@ protected: // const after set(), except for bits AUDIO_OUTPUT_FLAG_FAST and AUDIO_OUTPUT_FLAG_OFFLOAD. // mLock must be held to read or write those bits reliably. + bool mDoNotReconnect; + int mSessionId; int mAuxEffectId; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index fa917f9..8c36f0e 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -113,7 +113,8 @@ public: AudioCallback cb = NULL, void *cookie = NULL, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - const audio_offload_info_t *offloadInfo = NULL) = 0; + const audio_offload_info_t *offloadInfo = NULL, + bool doNotResuscitate = false) = 0; virtual status_t start() = 0; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index db316b0..faf5935 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -178,7 +178,8 @@ AudioTrack::AudioTrack( const audio_offload_info_t *offloadInfo, int uid, pid_t pid, - const audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes, + bool doNotReconnect) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -189,7 +190,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, - offloadInfo, uid, pid, pAttributes); + offloadInfo, uid, pid, pAttributes, doNotReconnect); } AudioTrack::AudioTrack( @@ -207,7 +208,8 @@ AudioTrack::AudioTrack( const audio_offload_info_t *offloadInfo, int uid, pid_t pid, - const audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes, + bool doNotReconnect) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -218,7 +220,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, - uid, pid, pAttributes); + uid, pid, pAttributes, doNotReconnect); } AudioTrack::~AudioTrack() @@ -266,7 +268,8 @@ status_t AudioTrack::set( const audio_offload_info_t *offloadInfo, int uid, pid_t pid, - const audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes, + bool doNotReconnect) { ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "flags #%x, notificationFrames %u, sessionId %d, transferType %d, uid %d, pid %d", @@ -308,6 +311,7 @@ status_t AudioTrack::set( } mSharedBuffer = sharedBuffer; mTransfer = transferType; + mDoNotReconnect = doNotReconnect; ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); @@ -2006,7 +2010,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) // output parameters and new IAudioFlinger in createTrack_l() AudioSystem::clearAudioConfigCache(); - if (isOffloadedOrDirect_l()) { + if (isOffloadedOrDirect_l() || mDoNotReconnect) { // FIXME re-creation of offloaded tracks is not yet implemented return DEAD_OBJECT; } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index efbc0d6..9c0af4a 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1489,7 +1489,8 @@ status_t MediaPlayerService::AudioOutput::open( audio_format_t format, int bufferCount, AudioCallback cb, void *cookie, audio_output_flags_t flags, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + bool doNotReconnect) { mCallback = cb; mCallbackCookie = cookie; @@ -1605,7 +1606,8 @@ status_t MediaPlayerService::AudioOutput::open( offloadInfo, mUid, mPid, - mAttributes); + mAttributes, + doNotReconnect); } else { t = new AudioTrack( mStreamType, @@ -1622,7 +1624,8 @@ status_t MediaPlayerService::AudioOutput::open( NULL, // offload info mUid, mPid, - mAttributes); + mAttributes, + doNotReconnect); } if ((t == 0) || (t->initCheck() != NO_ERROR)) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 5103841..e9f72b8 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -97,7 +97,8 @@ class MediaPlayerService : public BnMediaPlayerService audio_format_t format, int bufferCount, AudioCallback cb, void *cookie, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - const audio_offload_info_t *offloadInfo = NULL); + const audio_offload_info_t *offloadInfo = NULL, + bool doNotReconnect = false); virtual status_t start(); virtual ssize_t write(const void* buffer, size_t size, bool blocking = true); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 96a7adb..87074f0 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1083,12 +1083,12 @@ void NuPlayer::onMessageReceived(const sp &msg) { } else if (what == Renderer::kWhatMediaRenderingStart) { ALOGV("media rendering started"); notifyListener(MEDIA_STARTED, 0, 0); - } else if (what == Renderer::kWhatAudioOffloadTearDown) { - ALOGV("Tear down audio offload, fall back to s/w path if due to error."); + } else if (what == Renderer::kWhatAudioTearDown) { int64_t positionUs; CHECK(msg->findInt64("positionUs", &positionUs)); int32_t reason; CHECK(msg->findInt32("reason", &reason)); + ALOGV("Tear down audio with reason %d.", reason); closeAudioSink(); mAudioDecoder.clear(); ++mAudioDecoderGeneration; @@ -1100,9 +1100,22 @@ void NuPlayer::onMessageReceived(const sp &msg) { } performSeek(positionUs); + if (reason == Renderer::kDueToError) { - mRenderer->signalDisableOffloadAudio(); - mOffloadAudio = false; + sp audioMeta = mSource->getFormatMeta(true /* audio */); + sp videoFormat = mSource->getFormat(false /* audio */); + audio_stream_type_t streamType = mAudioSink->getAudioStreamType(); + const bool hasVideo = (videoFormat != NULL); + const bool canOffload = canOffloadStream( + audioMeta, hasVideo, true /* is_streaming */, streamType); + if (canOffload) { + mRenderer->signalEnableOffloadAudio(); + sp format = mSource->getFormat(true /*audio*/); + tryOpenAudioSinkForOffload(format, hasVideo); + } else { + mRenderer->signalDisableOffloadAudio(); + mOffloadAudio = false; + } instantiateDecoder(true /* audio */, &mAudioDecoder); } } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 376c93a..73f8ba8 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -68,6 +68,7 @@ NuPlayer::Decoder::Decoder( } NuPlayer::Decoder::~Decoder() { + mCodec->release(); releaseAndResetMediaBuffers(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 007a335..409dedf 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -82,7 +82,7 @@ NuPlayer::Renderer::Renderer( mVideoRenderingStartGeneration(0), mAudioRenderingStartGeneration(0), mAudioOffloadPauseTimeoutGeneration(0), - mAudioOffloadTornDown(false), + mAudioTornDown(false), mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER), mTotalBuffersQueued(0), @@ -566,9 +566,9 @@ void NuPlayer::Renderer::onMessageReceived(const sp &msg) { break; } - case kWhatAudioOffloadTearDown: + case kWhatAudioTearDown: { - onAudioOffloadTearDown(kDueToError); + onAudioTearDown(kDueToError); break; } @@ -580,7 +580,7 @@ void NuPlayer::Renderer::onMessageReceived(const sp &msg) { break; } ALOGV("Audio Offload tear down due to pause timeout."); - onAudioOffloadTearDown(kDueToTimeout); + onAudioTearDown(kDueToTimeout); mWakeLock->release(); break; } @@ -648,7 +648,7 @@ size_t NuPlayer::Renderer::AudioSinkCallback( case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN: { - me->notifyAudioOffloadTearDown(); + me->notifyAudioTearDown(); break; } } @@ -792,6 +792,7 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { ALOGW("AudioSink write would block when writing %zu bytes", copy); } else { ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy); + notifyAudioTearDown(); } break; } @@ -1060,8 +1061,8 @@ void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t del notify->post(delayUs); } -void NuPlayer::Renderer::notifyAudioOffloadTearDown() { - (new AMessage(kWhatAudioOffloadTearDown, this))->post(); +void NuPlayer::Renderer::notifyAudioTearDown() { + (new AMessage(kWhatAudioTearDown, this))->post(); } void NuPlayer::Renderer::onQueueBuffer(const sp &msg) { @@ -1480,11 +1481,11 @@ int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) { return durationUs; } -void NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reason) { - if (mAudioOffloadTornDown) { +void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) { + if (mAudioTornDown) { return; } - mAudioOffloadTornDown = true; + mAudioTornDown = true; int64_t currentPositionUs; if (getCurrentPosition(¤tPositionUs) != OK) { @@ -1495,7 +1496,7 @@ void NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reaso mAudioSink->flush(); sp notify = mNotify->dup(); - notify->setInt32("what", kWhatAudioOffloadTearDown); + notify->setInt32("what", kWhatAudioTearDown); notify->setInt64("positionUs", currentPositionUs); notify->setInt32("reason", reason); notify->post(); @@ -1653,7 +1654,9 @@ status_t NuPlayer::Renderer::onOpenAudioSink( 8 /* bufferCount */, NULL, NULL, - (audio_output_flags_t)pcmFlags); + (audio_output_flags_t)pcmFlags, + NULL, + true /* doNotReconnect */); if (err == OK) { err = mAudioSink->setPlaybackRate(mPlaybackSettings); } @@ -1668,9 +1671,7 @@ status_t NuPlayer::Renderer::onOpenAudioSink( if (audioSinkChanged) { onAudioSinkChanged(); } - if (offloadingAudio()) { - mAudioOffloadTornDown = false; - } + mAudioTornDown = false; return OK; } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 928b71b..fbdf5bf 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -82,16 +82,16 @@ struct NuPlayer::Renderer : public AHandler { void closeAudioSink(); enum { - kWhatEOS = 'eos ', - kWhatFlushComplete = 'fluC', - kWhatPosition = 'posi', - kWhatVideoRenderingStart = 'vdrd', - kWhatMediaRenderingStart = 'mdrd', - kWhatAudioOffloadTearDown = 'aOTD', + kWhatEOS = 'eos ', + kWhatFlushComplete = 'fluC', + kWhatPosition = 'posi', + kWhatVideoRenderingStart = 'vdrd', + kWhatMediaRenderingStart = 'mdrd', + kWhatAudioTearDown = 'adTD', kWhatAudioOffloadPauseTimeout = 'aOPT', }; - enum AudioOffloadTearDownReason { + enum AudioTearDownReason { kDueToError = 0, kDueToTimeout, }; @@ -179,7 +179,7 @@ private: int64_t mLastPositionUpdateUs; int32_t mAudioOffloadPauseTimeoutGeneration; - bool mAudioOffloadTornDown; + bool mAudioTornDown; audio_offload_info_t mCurrentOffloadInfo; struct PcmInfo { @@ -242,7 +242,7 @@ private: int32_t getQueueGeneration(bool audio); int32_t getDrainGeneration(bool audio); bool getSyncQueues(); - void onAudioOffloadTearDown(AudioOffloadTearDownReason reason); + void onAudioTearDown(AudioTearDownReason reason); status_t onOpenAudioSink( const sp &format, bool offloadOnly, @@ -255,7 +255,7 @@ private: void notifyPosition(); void notifyVideoLateBy(int64_t lateByUs); void notifyVideoRenderingStart(); - void notifyAudioOffloadTearDown(); + void notifyAudioTearDown(); void flushQueue(List *queue); bool dropBufferIfStale(bool audio, const sp &msg); -- cgit v1.1