OSDN Git Service

android/hal-audio: Return proper latency for stream
authorAndrzej Kaczmarek <andrzej.kaczmarek@tieto.com>
Wed, 22 Jan 2014 10:34:53 +0000 (11:34 +0100)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 23 Jan 2014 09:34:19 +0000 (11:34 +0200)
This patch implements get_latency() for output stream properly by
returning some meaningful value, i.e. calculated duration of single
media packet increased by fixed A2DP playback latency. This is the
same as PulseAudio does.

android/hal-audio.c

index 5e18c0b..2f5f3b5 100644 (file)
@@ -36,6 +36,8 @@
 #include "hal-msg.h"
 #include "../profiles/audio/a2dp-codecs.h"
 
+#define FIXED_A2DP_PLAYBACK_LATENCY_MS 25
+
 static const uint8_t a2dp_src_uuid[] = {
                0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
                0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
@@ -126,6 +128,7 @@ struct sbc_data {
        uint8_t *out_buf;
 
        unsigned frame_duration;
+       unsigned frames_per_packet;
 
        struct timespec start;
        unsigned frames_sent;
@@ -152,6 +155,7 @@ static int sbc_cleanup(void *codec_data);
 static int sbc_get_config(void *codec_data,
                                        struct audio_input_config *config);
 static size_t sbc_get_buffer_size(void *codec_data);
+static size_t sbc_get_mediapacket_duration(void *codec_data);
 static void sbc_resume(void *codec_data);
 static ssize_t sbc_write_data(void *codec_data, const void *buffer,
                                        size_t bytes, int fd);
@@ -167,6 +171,7 @@ struct audio_codec {
        int (*get_config) (void *codec_data,
                                        struct audio_input_config *config);
        size_t (*get_buffer_size) (void *codec_data);
+       size_t (*get_mediapacket_duration) (void *codec_data);
        void (*resume) (void *codec_data);
        ssize_t (*write_data) (void *codec_data, const void *buffer,
                                size_t bytes, int fd);
@@ -182,6 +187,7 @@ static const struct audio_codec audio_codecs[] = {
                .cleanup = sbc_cleanup,
                .get_config = sbc_get_config,
                .get_buffer_size = sbc_get_buffer_size,
+               .get_mediapacket_duration = sbc_get_mediapacket_duration,
                .resume = sbc_resume,
                .write_data = sbc_write_data,
        }
@@ -331,6 +337,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
        sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
 
        sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
+       sbc_data->frames_per_packet = num_frames;
 
        *codec_data = sbc_data;
 
@@ -388,6 +395,15 @@ static size_t sbc_get_buffer_size(void *codec_data)
        return sbc_data->in_buf_size;
 }
 
+static size_t sbc_get_mediapacket_duration(void *codec_data)
+{
+       struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+       DBG("");
+
+       return sbc_data->frame_duration * sbc_data->frames_per_packet;
+}
+
 static void sbc_resume(void *codec_data)
 {
        struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
@@ -949,8 +965,15 @@ static char *out_get_parameters(const struct audio_stream *stream,
 
 static uint32_t out_get_latency(const struct audio_stream_out *stream)
 {
+       struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+       struct audio_endpoint *ep = out->ep;
+       size_t pkt_duration;
+
        DBG("");
-       return 0;
+
+       pkt_duration = ep->codec->get_mediapacket_duration(ep->codec_data);
+
+       return FIXED_A2DP_PLAYBACK_LATENCY_MS + pkt_duration / 1000;
 }
 
 static int out_set_volume(struct audio_stream_out *stream, float left,