Merge pull request #683 from google/bigburst

oboe: use bigger burst in OpenSL ES
diff --git a/src/common/AudioStreamBuilder.cpp b/src/common/AudioStreamBuilder.cpp
index 58fc3be..401beea 100644
--- a/src/common/AudioStreamBuilder.cpp
+++ b/src/common/AudioStreamBuilder.cpp
@@ -163,7 +163,7 @@
         if (optimalBufferSize >= 0) {
             auto setBufferResult = streamP->setBufferSizeInFrames(optimalBufferSize);
             if (!setBufferResult) {
-                LOGW("Failed to set buffer size to %d. Error was %s",
+                LOGW("Failed to setBufferSizeInFrames(%d). Error was %s",
                      optimalBufferSize,
                      convertToText(setBufferResult.error()));
             }
diff --git a/src/opensles/AudioInputStreamOpenSLES.cpp b/src/opensles/AudioInputStreamOpenSLES.cpp
index 6b9ac5d..3c2d79b 100644
--- a/src/opensles/AudioInputStreamOpenSLES.cpp
+++ b/src/opensles/AudioInputStreamOpenSLES.cpp
@@ -196,12 +196,17 @@
         goto error;
     }
 
+    oboeResult = configureBufferSizes();
+    if (Result::OK != oboeResult) {
+        goto error;
+    }
+
     allocateFifo();
 
     setState(StreamState::Open);
     return Result::OK;
 
-    error:
+error:
     return Result::ErrorInternal; // TODO convert error from SLES to OBOE
 }
 
diff --git a/src/opensles/AudioOutputStreamOpenSLES.cpp b/src/opensles/AudioOutputStreamOpenSLES.cpp
index b94cdf3..2312a76 100644
--- a/src/opensles/AudioOutputStreamOpenSLES.cpp
+++ b/src/opensles/AudioOutputStreamOpenSLES.cpp
@@ -221,10 +221,16 @@
         goto error;
     }
 
+    oboeResult = configureBufferSizes();
+    if (Result::OK != oboeResult) {
+        goto error;
+    }
+
     allocateFifo();
 
     setState(StreamState::Open);
     return Result::OK;
+
 error:
     return Result::ErrorInternal; // TODO convert error from SLES to OBOE
 }
diff --git a/src/opensles/AudioStreamBuffered.cpp b/src/opensles/AudioStreamBuffered.cpp
index 42a7e58..51dd4d5 100644
--- a/src/opensles/AudioStreamBuffered.cpp
+++ b/src/opensles/AudioStreamBuffered.cpp
@@ -24,7 +24,7 @@
 namespace oboe {
 
 constexpr int kDefaultBurstsPerBuffer = 16;  // arbitrary, allows dynamic latency tuning
-
+constexpr int kMinFramesPerBuffer     = 48 * 32; // arbitrary
 /*
  * AudioStream with a FifoBuffer
  */
@@ -37,13 +37,14 @@
     // callback that reads data from the FIFO.
     if (usingFIFO()) {
         // FIFO is configured with the same format and channels as the stream.
-        int32_t capacity = getBufferCapacityInFrames();
-        if (capacity == oboe::kUnspecified) {
-            capacity = getFramesPerBurst() * kDefaultBurstsPerBuffer;
-            mBufferCapacityInFrames = capacity;
+        int32_t capacityFrames = getBufferCapacityInFrames();
+        if (capacityFrames == oboe::kUnspecified) {
+            capacityFrames = getFramesPerBurst() * kDefaultBurstsPerBuffer;
         }
+        capacityFrames = std::max(kMinFramesPerBuffer, capacityFrames);
         // TODO consider using std::make_unique if we require c++14
-        mFifoBuffer.reset(new FifoBuffer(getBytesPerFrame(), capacity));
+        mFifoBuffer.reset(new FifoBuffer(getBytesPerFrame(), capacityFrames));
+        mBufferCapacityInFrames = capacityFrames;
     }
 }
 
@@ -72,6 +73,8 @@
     }
 
     if (framesTransferred < numFrames) {
+        LOGD("AudioStreamBuffered::%s(): xrun! framesTransferred = %d, numFrames = %d",
+                __func__, framesTransferred, numFrames);
         // TODO If we do not allow FIFO to wrap then our timestamps will drift when there is an XRun!
         incrementXRunCount();
     }
diff --git a/src/opensles/AudioStreamOpenSLES.cpp b/src/opensles/AudioStreamOpenSLES.cpp
index e168edb..8d6b763 100644
--- a/src/opensles/AudioStreamOpenSLES.cpp
+++ b/src/opensles/AudioStreamOpenSLES.cpp
@@ -37,8 +37,9 @@
     mSessionId = SessionId::None;
 }
 
-constexpr SLuint32  kAudioChannelCountMax = 30;
-constexpr SLuint32  SL_ANDROID_UNKNOWN_CHANNELMASK  = 0; // Matches name used internally.
+static constexpr int32_t   kFramesPerHighLatencyBurst = 960; // typical, 20 msec at 48000
+static constexpr SLuint32  kAudioChannelCountMax = 30; // TODO Why 30?
+static constexpr SLuint32  SL_ANDROID_UNKNOWN_CHANNELMASK  = 0; // Matches name used internally.
 
 SLuint32 AudioStreamOpenSLES::channelCountToChannelMaskDefault(int channelCount) const {
     if (channelCount > kAudioChannelCountMax) {
@@ -69,7 +70,7 @@
 Result AudioStreamOpenSLES::open() {
 
     LOGI("AudioStreamOpenSLES::open(chans:%d, rate:%d)",
-                        mChannelCount, mSampleRate);
+         mChannelCount, mSampleRate);
 
     SLresult result = EngineOpenSLES::getInstance().open();
     if (SL_RESULT_SUCCESS != result) {
@@ -88,28 +89,35 @@
         mChannelCount = DefaultStreamValues::ChannelCount;
     }
 
+    mSharingMode = SharingMode::Shared;
+
+    return Result::OK;
+}
+
+Result AudioStreamOpenSLES::configureBufferSizes() {
     // Decide frames per burst based on hints from caller.
-    // TODO  Can we query this from OpenSL ES?
-    if (mFramesPerCallback != kUnspecified) {
-        mFramesPerBurst = mFramesPerCallback;
-    } else if (mFramesPerBurst != kUnspecified) { // set from defaultFramesPerBurst
-        mFramesPerCallback = mFramesPerBurst;
-    } else {
-        mFramesPerBurst = mFramesPerCallback = DefaultStreamValues::FramesPerBurst;
+    mFramesPerBurst = mFramesPerCallback;
+    if (mFramesPerBurst == kUnspecified) {
+        mFramesPerBurst = DefaultStreamValues::FramesPerBurst;
     }
+    // For high latency streams, use a larger buffer size.
+    if (mPerformanceMode != PerformanceMode::LowLatency
+        && mFramesPerBurst < kFramesPerHighLatencyBurst) {
+        mFramesPerBurst = kFramesPerHighLatencyBurst;
+        LOGD("AudioStreamOpenSLES:%s() NOT low latency, set mFramesPerBurst = %d",
+             __func__, mFramesPerBurst);
+    }
+    mFramesPerCallback = mFramesPerBurst;
 
     mBytesPerCallback = mFramesPerCallback * getBytesPerFrame();
-    LOGD("AudioStreamOpenSLES(): mFramesPerCallback = %d", mFramesPerCallback);
-    LOGD("AudioStreamOpenSLES(): mBytesPerCallback = %d", mBytesPerCallback);
     if (mBytesPerCallback <= 0) {
-        LOGE("AudioStreamOpenSLES::open() bytesPerCallback < 0, bad format?");
+        LOGE("AudioStreamOpenSLES::open() bytesPerCallback < 0 = %d, bad format?",
+             mBytesPerCallback);
         return Result::ErrorInvalidFormat; // causing bytesPerFrame == 0
     }
 
     mCallbackBuffer = std::make_unique<uint8_t[]>(mBytesPerCallback);
 
-    mSharingMode = SharingMode::Shared;
-
     if (!usingFIFO()) {
         mBufferCapacityInFrames = mFramesPerBurst * kBufferQueueLength;
         mBufferSizeInFrames = mBufferCapacityInFrames;
@@ -170,7 +178,6 @@
 
     SLresult result = SL_RESULT_SUCCESS;
     SLuint32 performanceMode = convertPerformanceMode(getPerformanceMode());
-    LOGD("SetConfiguration(SL_ANDROID_KEY_PERFORMANCE_MODE, SL %u) called", performanceMode);
     result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
                                                      &performanceMode, sizeof(performanceMode));
     if (SL_RESULT_SUCCESS != result) {
diff --git a/src/opensles/AudioStreamOpenSLES.h b/src/opensles/AudioStreamOpenSLES.h
index d1f362a..40220ab 100644
--- a/src/opensles/AudioStreamOpenSLES.h
+++ b/src/opensles/AudioStreamOpenSLES.h
@@ -100,6 +100,9 @@
     PerformanceMode convertPerformanceMode(SLuint32 openslMode) const;
     SLuint32 convertPerformanceMode(PerformanceMode oboeMode) const;
 
+
+    Result configureBufferSizes();
+
     /**
      * Internal use only.
      * Use this instead of directly setting the internal state variable.