NuPlayer: Reserve buffer for 8x max speed
Affects Photos with Bluetooth and 240x recording.
Bug: 26986060
Change-Id: I228223221f9811e05c274d64cd42ac104db04c36
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index a4cc3d7..27db7b3 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -191,7 +191,8 @@
int uid,
pid_t pid,
const audio_attributes_t* pAttributes,
- bool doNotReconnect)
+ bool doNotReconnect,
+ float maxRequiredSpeed)
: mStatus(NO_INIT),
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -202,7 +203,7 @@
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
- offloadInfo, uid, pid, pAttributes, doNotReconnect);
+ offloadInfo, uid, pid, pAttributes, doNotReconnect, maxRequiredSpeed);
}
AudioTrack::AudioTrack(
@@ -221,7 +222,8 @@
int uid,
pid_t pid,
const audio_attributes_t* pAttributes,
- bool doNotReconnect)
+ bool doNotReconnect,
+ float maxRequiredSpeed)
: mStatus(NO_INIT),
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -232,7 +234,7 @@
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- uid, pid, pAttributes, doNotReconnect);
+ uid, pid, pAttributes, doNotReconnect, maxRequiredSpeed);
}
AudioTrack::~AudioTrack()
@@ -281,7 +283,8 @@
int uid,
pid_t pid,
const audio_attributes_t* pAttributes,
- bool doNotReconnect)
+ bool doNotReconnect,
+ float maxRequiredSpeed)
{
ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"flags #%x, notificationFrames %u, sessionId %d, transferType %d, uid %d, pid %d",
@@ -422,6 +425,8 @@
mSampleRate = sampleRate;
mOriginalSampleRate = sampleRate;
mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
+ // 1.0 <= mMaxRequiredSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX
+ mMaxRequiredSpeed = min(max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
// Make copy of input parameter offloadInfo so that in the future:
// (a) createTrack_l doesn't need it as an input parameter
@@ -824,6 +829,9 @@
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
return INVALID_OPERATION;
}
+
+ ALOGV("setPlaybackRate (input): mSampleRate:%u mSpeed:%f mPitch:%f",
+ mSampleRate, playbackRate.mSpeed, playbackRate.mPitch);
// pitch is emulated by adjusting speed and sampleRate
const uint32_t effectiveRate = adjustSampleRate(mSampleRate, playbackRate.mPitch);
const float effectiveSpeed = adjustSpeed(playbackRate.mSpeed, playbackRate.mPitch);
@@ -832,12 +840,18 @@
playbackRateTemp.mSpeed = effectiveSpeed;
playbackRateTemp.mPitch = effectivePitch;
+ ALOGV("setPlaybackRate (effective): mSampleRate:%u mSpeed:%f mPitch:%f",
+ effectiveRate, effectiveSpeed, effectivePitch);
+
if (!isAudioPlaybackRateValid(playbackRateTemp)) {
+ ALOGV("setPlaybackRate(%f, %f) failed (effective rate out of bounds)",
+ playbackRate.mSpeed, playbackRate.mPitch);
return BAD_VALUE;
}
// Check if the buffer size is compatible.
if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) {
- ALOGV("setPlaybackRate(%f, %f) failed", playbackRate.mSpeed, playbackRate.mPitch);
+ ALOGV("setPlaybackRate(%f, %f) failed (buffer size)",
+ playbackRate.mSpeed, playbackRate.mPitch);
return BAD_VALUE;
}
@@ -1275,9 +1289,11 @@
if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
// for normal tracks precompute the frame count based on speed.
+ const float speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
+ max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
const size_t minFrameCount = calculateMinFrameCount(
mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate,
- mPlaybackRate.mSpeed);
+ speed);
if (frameCount < minFrameCount) {
frameCount = minFrameCount;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 1a3013a..2afbdb4 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -94,6 +94,8 @@
// Max number of entries in the filter.
const int kMaxFilterSize = 64; // I pulled that out of thin air.
+const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
+
// FIXME: Move all the metadata related function in the Metadata.cpp
@@ -1749,6 +1751,14 @@
mAttributes,
doNotReconnect);
} else {
+ // TODO: Due to buffer memory concerns, we use a max target playback speed
+ // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
+ // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
+ const float targetSpeed =
+ std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
+ ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
+ "track target speed:%f clamped from playback speed:%f",
+ targetSpeed, mPlaybackRate.mSpeed);
t = new AudioTrack(
mStreamType,
sampleRate,
@@ -1765,7 +1775,8 @@
mUid,
mPid,
mAttributes,
- doNotReconnect);
+ doNotReconnect,
+ targetSpeed);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index cbb9d95..5f36fc1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1876,6 +1876,10 @@
// NuPlayer a chance to switch from non-offload mode to offload mode.
// So we only set doNotReconnect when there's no video.
const bool doNotReconnect = !hasVideo;
+
+ // We should always be able to set our playback settings if the sink is closed.
+ LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
+ "onOpenAudioSink: can't set playback rate on closed sink");
status_t err = mAudioSink->open(
sampleRate,
numChannels,
@@ -1888,9 +1892,6 @@
NULL,
doNotReconnect,
frameCount);
- if (err == OK) {
- err = mAudioSink->setPlaybackRate(mPlaybackSettings);
- }
if (err != OK) {
ALOGW("openAudioSink: non offloaded open failed status: %d", err);
mAudioSink->close();