diff options
Diffstat (limited to 'media/libmediaplayerservice/MediaPlayerService.cpp')
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 4e57813..ae869d6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1482,20 +1482,11 @@ status_t MediaPlayerService::AudioOutput::open( AudioCallback cb, void *cookie, audio_output_flags_t flags, const audio_offload_info_t *offloadInfo, - bool doNotReconnect) + bool doNotReconnect, + uint32_t suggestedFrameCount) { - mCallback = cb; - mCallbackCookie = cookie; - - // Check argument "bufferCount" against the mininum buffer count - if (bufferCount < mMinBufferCount) { - ALOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount); - bufferCount = mMinBufferCount; - - } ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask, format, bufferCount, mSessionId, flags); - size_t frameCount; // offloading is only supported in callback mode for now. // offloadInfo must be present if offload flag is set @@ -1504,20 +1495,36 @@ status_t MediaPlayerService::AudioOutput::open( return BAD_VALUE; } + // compute frame count for the AudioTrack internal buffer + size_t frameCount; if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { frameCount = 0; // AudioTrack will get frame count from AudioFlinger } else { + // try to estimate the buffer processing fetch size from AudioFlinger. + // framesPerBuffer is approximate and generally correct, except when it's not :-). uint32_t afSampleRate; size_t afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { return NO_INIT; } if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { return NO_INIT; } + const size_t framesPerBuffer = + (unsigned long long)sampleRate * afFrameCount / afSampleRate; - frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate; + if (bufferCount == 0) { + // use suggestedFrameCount + bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer; + } + // Check argument bufferCount against the mininum buffer count + if (bufferCount != 0 && bufferCount < mMinBufferCount) { + ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount); + bufferCount = mMinBufferCount; + } + // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger + // which will be the minimum size permitted. + frameCount = bufferCount * framesPerBuffer; } if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) { @@ -1528,6 +1535,9 @@ status_t MediaPlayerService::AudioOutput::open( } } + mCallback = cb; + mCallbackCookie = cookie; + // Check whether we can recycle the track bool reuse = false; bool bothOffloaded = false; @@ -1746,12 +1756,14 @@ ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, void MediaPlayerService::AudioOutput::stop() { ALOGV("stop"); + mBytesWritten = 0; if (mTrack != 0) mTrack->stop(); } void MediaPlayerService::AudioOutput::flush() { ALOGV("flush"); + mBytesWritten = 0; if (mTrack != 0) mTrack->flush(); } @@ -1853,20 +1865,23 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( me, buffer->raw, buffer->size, me->mCallbackCookie, CB_EVENT_FILL_BUFFER); - if ((me->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0 && - actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) { - // We've reached EOS but the audio track is not stopped yet, - // keep playing silence. + // Log when no data is returned from the callback. + // (1) We may have no data (especially with network streaming sources). + // (2) We may have reached the EOS and the audio track is not stopped yet. + // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS. + // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill). + // + // This is a benign busy-wait, with the next data request generated 10 ms or more later; + // nevertheless for power reasons, we don't want to see too many of these. - memset(buffer->raw, 0, buffer->size); - actualSize = buffer->size; - } + ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned"); + me->mBytesWritten += actualSize; // benign race with reader. buffer->size = actualSize; } break; - case AudioTrack::EVENT_STREAM_END: + // currently only occurs for offloaded callbacks ALOGV("callbackwrapper: deliver EVENT_STREAM_END"); (*me->mCallback)(me, NULL /* buffer */, 0 /* size */, me->mCallbackCookie, CB_EVENT_STREAM_END); @@ -1879,11 +1894,15 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( break; case AudioTrack::EVENT_UNDERRUN: - // This occurs when there is no data available, typically occurring + // This occurs when there is no data available, typically // when there is a failure to supply data to the AudioTrack. It can also // occur in non-offloaded mode when the audio device comes out of standby. // - // If you see this at the start of playback, there probably was a glitch. + // If an AudioTrack underruns it outputs silence. Since this happens suddenly + // it may sound like an audible pop or glitch. + // + // The underrun event is sent once per track underrun; the condition is reset + // when more data is sent to the AudioTrack. ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)"); break; |