summaryrefslogtreecommitdiffstats
path: root/alsa_utils
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2015-08-04 14:57:50 -0700
committerAndy Hung <hunga@google.com>2015-08-06 14:51:45 -0700
commit8785fe142d519d8e011eecdc340a638978fb9272 (patch)
tree7c06d4be75d6c89d27970d0bedc42df71c84a021 /alsa_utils
parent8b6721ca77a780e2d88c6299684b454952105481 (diff)
downloadandroid_system_media-8785fe142d519d8e011eecdc340a638978fb9272.tar.gz
android_system_media-8785fe142d519d8e011eecdc340a638978fb9272.tar.bz2
android_system_media-8785fe142d519d8e011eecdc340a638978fb9272.zip
Add USB proxy_get_presentation_position() for timestamps
Bug: 21196672 Change-Id: I7e5d7434935a15ef6bfc7630e16a7895f5e605d6
Diffstat (limited to 'alsa_utils')
-rw-r--r--alsa_utils/alsa_device_profile.c8
-rw-r--r--alsa_utils/alsa_device_proxy.c52
-rw-r--r--alsa_utils/include/alsa_device_proxy.h8
3 files changed, 56 insertions, 12 deletions
diff --git a/alsa_utils/alsa_device_profile.c b/alsa_utils/alsa_device_profile.c
index c9f8f998..dd238e74 100644
--- a/alsa_utils/alsa_device_profile.c
+++ b/alsa_utils/alsa_device_profile.c
@@ -44,14 +44,6 @@ static const char * const format_string_map[] = {
"AUDIO_FORMAT_PCM_24_BIT_PACKED"/* "PCM_FORMAT_S24_3LE" */
};
-static const unsigned const format_byte_size_map[] = {
- 2, /* PCM_FORMAT_S16_LE */
- 4, /* PCM_FORMAT_S32_LE */
- 1, /* PCM_FORMAT_S8 */
- 4, /* PCM_FORMAT_S24_LE */
- 3, /* PCM_FORMAT_S24_3LE */
-};
-
extern int8_t const pcm_format_value_map[50];
/* Sort these in terms of preference (best first).
diff --git a/alsa_utils/alsa_device_proxy.c b/alsa_utils/alsa_device_proxy.c
index d2d8b6f1..ac948f12 100644
--- a/alsa_utils/alsa_device_proxy.c
+++ b/alsa_utils/alsa_device_proxy.c
@@ -29,6 +29,16 @@
#define DEFAULT_PERIOD_SIZE 1024
#define DEFAULT_PERIOD_COUNT 2
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const unsigned format_byte_size_map[] = {
+ 2, /* PCM_FORMAT_S16_LE */
+ 4, /* PCM_FORMAT_S32_LE */
+ 1, /* PCM_FORMAT_S8 */
+ 4, /* PCM_FORMAT_S24_LE */
+ 3, /* PCM_FORMAT_S24_3LE */
+};
+
void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
struct pcm_config * config)
{
@@ -62,6 +72,12 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
}
proxy->pcm = NULL;
+ // config format should be checked earlier against profile.
+ if (config->format >= 0 && (size_t)config->format < ARRAY_SIZE(format_byte_size_map)) {
+ proxy->frame_size = format_byte_size_map[config->format] * proxy->alsa_config.channels;
+ } else {
+ proxy->frame_size = 1;
+ }
}
int proxy_open(alsa_device_proxy * proxy)
@@ -74,7 +90,8 @@ int proxy_open(alsa_device_proxy * proxy)
return -EINVAL;
}
- proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config);
+ proxy->pcm = pcm_open(profile->card, profile->device,
+ profile->direction | PCM_MONOTONIC, &proxy->alsa_config);
if (proxy->pcm == NULL) {
return -ENOMEM;
}
@@ -145,12 +162,41 @@ unsigned proxy_get_latency(const alsa_device_proxy * proxy)
/ proxy_get_sample_rate(proxy);
}
+int proxy_get_presentation_position(const alsa_device_proxy * proxy,
+ uint64_t *frames, struct timespec *timestamp)
+{
+ int ret = -EPERM; // -1
+ unsigned int avail;
+ if (proxy->pcm != NULL
+ && pcm_get_htimestamp(proxy->pcm, &avail, timestamp) == 0) {
+ const size_t kernel_buffer_size =
+ proxy->alsa_config.period_size * proxy->alsa_config.period_count;
+ if (avail > kernel_buffer_size) {
+ ALOGE("available frames(%u) > buffer size(%zu)", avail, kernel_buffer_size);
+ } else {
+ int64_t signed_frames = proxy->transferred - kernel_buffer_size + avail;
+ // It is possible to compensate for additional driver and device delay
+ // by changing signed_frames. Example:
+ // signed_frames -= 20 /* ms */ * proxy->alsa_config.rate / 1000;
+ if (signed_frames >= 0) {
+ *frames = signed_frames;
+ ret = 0;
+ }
+ }
+ }
+ return ret;
+}
+
/*
* I/O
*/
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count)
+int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count)
{
- return pcm_write(proxy->pcm, data, count);
+ int ret = pcm_write(proxy->pcm, data, count);
+ if (ret == 0) {
+ proxy->transferred += count / proxy->frame_size;
+ }
+ return ret;
}
int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count)
diff --git a/alsa_utils/include/alsa_device_proxy.h b/alsa_utils/include/alsa_device_proxy.h
index add73156..e1ff8f5f 100644
--- a/alsa_utils/include/alsa_device_proxy.h
+++ b/alsa_utils/include/alsa_device_proxy.h
@@ -27,6 +27,9 @@ typedef struct {
struct pcm_config alsa_config;
struct pcm * pcm;
+
+ size_t frame_size; /* valid after proxy_prepare(), the frame size in bytes */
+ uint64_t transferred; /* the total frames transferred, not cleared on standby */
} alsa_device_proxy;
void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
@@ -40,10 +43,13 @@ unsigned int proxy_get_period_size(const alsa_device_proxy * proxy);
unsigned proxy_get_latency(const alsa_device_proxy * proxy);
+int proxy_get_presentation_position(const alsa_device_proxy * proxy,
+ uint64_t *frames, struct timespec *timestamp);
+
int proxy_open(alsa_device_proxy * proxy);
void proxy_close(alsa_device_proxy * proxy);
-int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count);
+int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count);
int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count);
#endif /* ANDROID_SYSTEM_MEDIA_ALSA_UTILS_ALSA_DEVICE_PROXY_H */