OSDN Git Service

Match socket buffer sizes between audio HAL and BT server
authorAndy Hung <hunga@google.com>
Fri, 6 May 2016 00:26:44 +0000 (00:26 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Fri, 6 May 2016 00:26:44 +0000 (00:26 +0000)
am: e97d975cce

* commit 'e97d975cce213b8c6e4f69bc3fc75411a1743647':
  Match socket buffer sizes between audio HAL and BT server

Change-Id: Ib257ca1ea7a5c73cd0f6e8c84703e5d7d58cccf3

audio_a2dp_hw/audio_a2dp_hw.c
audio_a2dp_hw/audio_a2dp_hw.h
udrv/ulinux/uipc.c

index df2b92b..59efd35 100644 (file)
@@ -638,10 +638,16 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
 static size_t out_get_buffer_size(const struct audio_stream *stream)
 {
     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
+    // period_size is the AudioFlinger mixer buffer size.
+    const size_t period_size = out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
+    const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */;
 
-    DEBUG("buffer_size : %zu", out->common.buffer_sz);
+    DEBUG("socket buffer size: %zu  period size: %zu", out->common.buffer_sz, period_size);
+    if (period_size % mixer_unit_size != 0) {
+        ERROR("period size %zu not a multiple of %zu", period_size, mixer_unit_size);
+    }
 
-    return out->common.buffer_sz;
+    return period_size;
 }
 
 static uint32_t out_get_channels(const struct audio_stream *stream)
index 901fafb..11d438a 100644 (file)
 #define AUDIO_STREAM_DEFAULT_RATE          44100
 #define AUDIO_STREAM_DEFAULT_FORMAT        AUDIO_FORMAT_PCM_16_BIT
 #define AUDIO_STREAM_DEFAULT_CHANNEL_FLAG  AUDIO_CHANNEL_OUT_STEREO
-#define AUDIO_STREAM_OUTPUT_BUFFER_SZ      (20*512)
+
+// AUDIO_STREAM_OUTPUT_BUFFER_SZ controls the size of the audio socket buffer.
+// If one assumes the write buffer is always full during normal BT playback,
+// then increasing this value increases our playback latency.
+//
+// FIXME: AUDIO_STREAM_OUTPUT_BUFFER_SZ should be controlled by the actual audio
+// sample rate rather than being constant.
+//
+// FIXME: The BT HAL should consume data at a constant rate.
+// AudioFlinger assumes that the HAL draws data at a constant rate, which is true
+// for most audio devices; however, the BT engine reads data at a variable rate
+// (over the short term), which confuses both AudioFlinger as well as applications
+// which deliver data at a (generally) fixed rate.
+//
+// 20 * 512 is not sufficient size to smooth the variability for some BT devices,
+// resulting in mixer sleep and throttling. We increase this to 28 * 512 to help
+// reduce the effect of variable data consumption.
+#define AUDIO_STREAM_OUTPUT_BUFFER_SZ      (28*512)
+
+// AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is divided
+// for AudioFlinger data delivery. The AudioFlinger mixer delivers data in chunks
+// of AUDIO_STREAM_OUTPUT_BUFFER_SZ / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS. If
+// the number of periods is 2, the socket buffer represents "double buffering"
+// of the AudioFlinger mixer buffer.
+//
+// In general, AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 * 4 should be a divisor of
+// AUDIO_STREAM_OUTPUT_BUFFER_SZ.
+//
+// These values should be chosen such that
+//
+// AUDIO_STREAM_BUFFER_SIZE * 1000 / (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS
+//         * AUDIO_STREAM_DEFAULT_RATE * 4) > 20 (ms)
+//
+// to avoid introducing the FastMixer in AudioFlinger. Using the FastMixer results in
+// unnecessary latency and CPU overhead for Bluetooth.
+#define AUDIO_STREAM_OUTPUT_BUFFER_PERIODS 4
+
 #define AUDIO_SKT_DISCONNECTED             (-1)
 
 typedef enum {
index 4256aed..e932c90 100644 (file)
@@ -193,6 +193,13 @@ static int accept_server_socket(int sfd)
          return -1;
     }
 
+    // match socket buffer size option with client
+    const int size = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
+    int ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
+    if (ret < 0) {
+        BTIF_TRACE_ERROR("setsockopt failed (%s)", strerror(errno));
+    }
+
     //BTIF_TRACE_EVENT("new fd %d", fd);
 
     return fd;