/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include #include #include #include #include #include #include #include #include "audio_thread.h" #include "audio_thread_log.h" #include "byte_buffer.h" #include "cras_iodev_list.h" #include "cras_a2dp_endpoint.h" #include "cras_a2dp_info.h" #include "cras_a2dp_iodev.h" #include "cras_audio_area.h" #include "cras_audio_thread_monitor.h" #include "cras_bt_device.h" #include "cras_iodev.h" #include "cras_util.h" #include "rtp.h" #include "utlist.h" #define PCM_BUF_MAX_SIZE_FRAMES (4096 * 4) #define PCM_BUF_MAX_SIZE_BYTES (PCM_BUF_MAX_SIZE_FRAMES * 4) /* Threshold for reasonable a2dp throttle log in audio dump. */ static const struct timespec throttle_log_threshold = { 0, 20000000 /* 20ms */ }; /* Threshold for severe a2dp throttle event. */ static const struct timespec throttle_event_threshold = { 2, 0 /* 2s */ }; /* Child of cras_iodev to handle bluetooth A2DP streaming. * Members: * base - The cras_iodev structure "base class" * a2dp - The codec and encoded state of a2dp_io. * transport - The transport object for bluez media API. * sock_depth_frames - Socket depth in frames of the a2dp socket. * pcm_buf - Buffer to hold pcm samples before encode. * destroyed - Flag to note if this a2dp_io is about to destroy. * next_flush_time - The time when it is okay for next flush call. * flush_period - The time period between two a2dp packet writes. * write_block - How many frames of audio samples are transferred in one * a2dp packet write. */ struct a2dp_io { struct cras_iodev base; struct a2dp_info a2dp; struct cras_bt_transport *transport; unsigned sock_depth_frames; struct byte_buffer *pcm_buf; int destroyed; struct timespec next_flush_time; struct timespec flush_period; unsigned int write_block; }; static int encode_and_flush(const struct cras_iodev *iodev); static int update_supported_formats(struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; size_t rate = 0; size_t channel; a2dp_sbc_t a2dp; cras_bt_transport_configuration(a2dpio->transport, &a2dp, sizeof(a2dp)); channel = (a2dp.channel_mode == SBC_CHANNEL_MODE_MONO) ? 1 : 2; if (a2dp.frequency & SBC_SAMPLING_FREQ_48000) rate = 48000; else if (a2dp.frequency & SBC_SAMPLING_FREQ_44100) rate = 44100; else if (a2dp.frequency & SBC_SAMPLING_FREQ_32000) rate = 32000; else if (a2dp.frequency & SBC_SAMPLING_FREQ_16000) rate = 16000; free(iodev->supported_rates); iodev->supported_rates = (size_t *)malloc(2 * sizeof(rate)); iodev->supported_rates[0] = rate; iodev->supported_rates[1] = 0; free(iodev->supported_channel_counts); iodev->supported_channel_counts = (size_t *)malloc(2 * sizeof(channel)); iodev->supported_channel_counts[0] = channel; iodev->supported_channel_counts[1] = 0; free(iodev->supported_formats); iodev->supported_formats = (snd_pcm_format_t *)malloc(2 * sizeof(snd_pcm_format_t)); iodev->supported_formats[0] = SND_PCM_FORMAT_S16_LE; iodev->supported_formats[1] = (snd_pcm_format_t)0; return 0; } static unsigned int bt_local_queued_frames(const struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; return a2dp_queued_frames(&a2dpio->a2dp) + buf_queued(a2dpio->pcm_buf) / cras_get_format_bytes(iodev->format); } static int frames_queued(const struct cras_iodev *iodev, struct timespec *tstamp) { int local_queued_frames = bt_local_queued_frames(iodev); clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); return MIN(iodev->buffer_size, local_queued_frames); } /* * Utility function to fill zero frames until buffer level reaches * target_level. This is useful to allocate just enough data to write * to controller, while not introducing extra latency. */ static int fill_zeros_to_target_level(struct cras_iodev *iodev, unsigned int target_level) { unsigned int local_queued_frames = bt_local_queued_frames(iodev); if (local_queued_frames < target_level) return cras_iodev_fill_odev_zeros( iodev, target_level - local_queued_frames); return 0; } /* * dev_io_playback_write() has the logic to detect underrun scenario * and calls into this underrun ops, by comparing buffer level with * number of frames just written. Note that it's not correct 100% of * the time in a2dp case, because we lose track of samples once they're * flushed to socket. */ static int output_underrun(struct cras_iodev *iodev) { unsigned int local_queued_frames = bt_local_queued_frames(iodev); /* * Examples to help understand the check: * * [False-positive underrun] * Assume min_buffer_level = 1000, written 900, and flushes * 800 of data. Audio thread sees 1000 + 900 - 800 = 1100 of * data left. This is merely 100(< 900) above min_buffer_level * so audio_thread thinks it underruns, but actually not. * * [True underrun] * min_buffer_level = 1000, written 200, and flushes 800 of * data. Now that buffer runs lower than min_buffer_level so * it's indeed an underrun. */ if (local_queued_frames > iodev->min_buffer_level) return 0; return cras_iodev_fill_odev_zeros(iodev, iodev->min_cb_level); } /* * This will be called multiple times when a2dpio is in no_stream state * frames_to_play_in_sleep ops determins how regular this will be called. */ static int enter_no_stream(struct a2dp_io *a2dpio) { struct cras_iodev *odev = &a2dpio->base; int rc; /* * Setting target level to 3 times of min_buffer_level. * We want hw_level to stay bewteen 1-2 times of min_buffer_level on * top of the underrun threshold(i.e one min_cb_level). */ rc = fill_zeros_to_target_level(odev, 3 * odev->min_buffer_level); if (rc) syslog(LOG_ERR, "Error in A2DP enter_no_stream"); return encode_and_flush(odev); } /* * This is called when stream data is available to write. Prepare audio * data to one min_buffer_level. Don't flush it now because stream data is * coming right up which will trigger next flush at appropriate time. */ static int leave_no_stream(struct a2dp_io *a2dpio) { struct cras_iodev *odev = &a2dpio->base; /* * Since stream data is ready, just make sure hw_level doesn't underrun * after one flush. Hence setting the target level to 2 times of * min_buffer_level. */ return fill_zeros_to_target_level(odev, 2 * odev->min_buffer_level); } /* * Makes sure there's enough data(zero frames) to flush when no stream presents. * Note that the underrun condition is when real buffer level goes below * min_buffer_level, so we want to keep data at a reasonable higher level on top * of that. */ static int no_stream(struct cras_iodev *odev, int enable) { struct a2dp_io *a2dpio = (struct a2dp_io *)odev; if (enable) return enter_no_stream(a2dpio); else return leave_no_stream(a2dpio); } /* Encode as much PCM data as we can until the buffer level of a2dp_info * reaches MTU. * Returns: * 0 for success, otherwise negative error code. */ static int encode_a2dp_packet(struct a2dp_io *a2dpio) { int processed; size_t format_bytes = cras_get_format_bytes(a2dpio->base.format); while (buf_queued(a2dpio->pcm_buf)) { processed = a2dp_encode( &a2dpio->a2dp, buf_read_pointer(a2dpio->pcm_buf), buf_readable(a2dpio->pcm_buf), format_bytes, cras_bt_transport_write_mtu(a2dpio->transport)); if (processed == -ENOSPC || processed == 0) break; if (processed < 0) return processed; buf_increment_read(a2dpio->pcm_buf, processed); } return 0; } /* * To be called when a2dp socket becomes writable. */ static int a2dp_socket_write_cb(void *arg, int revent) { struct cras_iodev *iodev = (struct cras_iodev *)arg; return encode_and_flush(iodev); } static int configure_dev(struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; int sock_depth; int err; socklen_t optlen; int a2dp_payload_length; err = cras_bt_transport_acquire(a2dpio->transport); if (err < 0) { syslog(LOG_ERR, "transport_acquire failed"); return err; } /* Apply the node's volume after transport is acquired. Doing this * is necessary because the volume can not sync to hardware until * it is opened. */ iodev->set_volume(iodev); /* Assert format is set before opening device. */ if (iodev->format == NULL) return -EINVAL; iodev->format->format = SND_PCM_FORMAT_S16_LE; cras_iodev_init_audio_area(iodev, iodev->format->num_channels); a2dpio->pcm_buf = byte_buffer_create(PCM_BUF_MAX_SIZE_BYTES); if (!a2dpio->pcm_buf) return -ENOMEM; /* Set up the socket to hold two MTUs full of data before returning * EAGAIN. This will allow the write to be throttled when a reasonable * amount of data is queued. */ sock_depth = 2 * cras_bt_transport_write_mtu(a2dpio->transport); setsockopt(cras_bt_transport_fd(a2dpio->transport), SOL_SOCKET, SO_SNDBUF, &sock_depth, sizeof(sock_depth)); optlen = sizeof(sock_depth); getsockopt(cras_bt_transport_fd(a2dpio->transport), SOL_SOCKET, SO_SNDBUF, &sock_depth, &optlen); a2dpio->sock_depth_frames = a2dp_block_size(&a2dpio->a2dp, sock_depth) / cras_get_format_bytes(iodev->format); /* * Per avdtp_write, subtract the room for packet header first. * Calculate how many frames are encapsulated in one a2dp packet, and * the corresponding time period between two packets. */ a2dp_payload_length = cras_bt_transport_write_mtu(a2dpio->transport) - sizeof(struct rtp_header) - sizeof(struct rtp_payload); a2dpio->write_block = a2dp_block_size(&a2dpio->a2dp, a2dp_payload_length) / cras_get_format_bytes(iodev->format); cras_frames_to_time(a2dpio->write_block, iodev->format->frame_rate, &a2dpio->flush_period); /* PCM buffer size plus one encoded a2dp packet. */ iodev->buffer_size = PCM_BUF_MAX_SIZE_FRAMES + a2dpio->write_block; /* * Buffer level less than one write_block can't be send over a2dp * packet. Configure min_buffer_level to this value so when stream * underruns, audio thread can take action to fill some zeros. */ iodev->min_buffer_level = a2dpio->write_block; audio_thread_add_events_callback( cras_bt_transport_fd(a2dpio->transport), a2dp_socket_write_cb, iodev, POLLOUT | POLLERR | POLLHUP); audio_thread_config_events_callback( cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); return 0; } static int start(const struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; /* * This is called when iodev in open state, at the moment when * output sample is ready. Initialize the next_flush_time for * following flush calls. */ clock_gettime(CLOCK_MONOTONIC_RAW, &a2dpio->next_flush_time); return 0; } static int close_dev(struct cras_iodev *iodev) { int err; struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; struct cras_bt_device *device; if (!a2dpio->transport) return 0; /* Remove audio thread callback and sync before releasing * the transport. */ audio_thread_rm_callback_sync(cras_iodev_list_get_audio_thread(), cras_bt_transport_fd(a2dpio->transport)); err = cras_bt_transport_release(a2dpio->transport, !a2dpio->destroyed); if (err < 0) syslog(LOG_ERR, "transport_release failed"); device = cras_bt_transport_device(a2dpio->transport); if (device) cras_bt_device_cancel_suspend(device); a2dp_reset(&a2dpio->a2dp); byte_buffer_destroy(&a2dpio->pcm_buf); cras_iodev_free_format(iodev); cras_iodev_free_audio_area(iodev); return 0; } static unsigned int frames_to_play_in_sleep(struct cras_iodev *iodev, unsigned int *hw_level, struct timespec *hw_tstamp) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; int frames_until; *hw_level = frames_queued(iodev, hw_tstamp); if (*hw_level < a2dpio->write_block) *hw_level = 0; else *hw_level -= a2dpio->write_block; frames_until = cras_frames_until_time(&a2dpio->next_flush_time, iodev->format->frame_rate); if (frames_until > 0) return frames_until; /* If time has passed next_flush_time, for example when socket write * throttles, sleep a moderate of time so that audio thread doesn't * busy wake up. */ return a2dpio->write_block; } /* Encodes PCM data to a2dp frames and try to flush it to the socket. * Returns: * 0 when the flush succeeded, -1 when error occurred. */ static int encode_and_flush(const struct cras_iodev *iodev) { int err; size_t format_bytes; int written = 0; unsigned int queued_frames; struct a2dp_io *a2dpio; struct cras_bt_device *device; struct timespec now, ts; static const struct timespec flush_wake_fuzz_ts = { 0, 1000000 /* 1ms */ }; a2dpio = (struct a2dp_io *)iodev; format_bytes = cras_get_format_bytes(iodev->format); device = cras_bt_transport_device(a2dpio->transport); /* If bt device has been destroyed, this a2dp iodev will soon be * destroyed as well. */ if (device == NULL) return -EINVAL; ATLOG(atlog, AUDIO_THREAD_A2DP_FLUSH, iodev->state, a2dpio->next_flush_time.tv_sec, a2dpio->next_flush_time.tv_nsec); /* Only allow data to be flushed after start() ops is called. */ if ((iodev->state != CRAS_IODEV_STATE_NORMAL_RUN) && (iodev->state != CRAS_IODEV_STATE_NO_STREAM_RUN)) return 0; err = encode_a2dp_packet(a2dpio); if (err < 0) return err; do_flush: /* If flush gets called before targeted next flush time, do nothing. */ clock_gettime(CLOCK_MONOTONIC_RAW, &now); add_timespecs(&now, &flush_wake_fuzz_ts); if (!timespec_after(&now, &a2dpio->next_flush_time)) { if (iodev->buffer_size == bt_local_queued_frames(iodev)) { /* * If buffer is full, audio thread will no longer call * into get/put buffer in subsequent wake-ups. In that * case set the registered callback to be triggered at * next audio thread wake up. */ audio_thread_config_events_callback( cras_bt_transport_fd(a2dpio->transport), TRIGGER_WAKEUP); cras_audio_thread_event_a2dp_overrun(); syslog(LOG_WARNING, "Buffer overrun in A2DP iodev"); } return 0; } /* If the A2DP write schedule miss exceeds a small threshold, log it for * debug purpose. */ subtract_timespecs(&now, &a2dpio->next_flush_time, &ts); if (timespec_after(&ts, &throttle_log_threshold)) ATLOG(atlog, AUDIO_THREAD_A2DP_THROTTLE_TIME, ts.tv_sec, ts.tv_nsec, bt_local_queued_frames(iodev)); /* Log an event if the A2DP write schedule miss exceeds a large threshold * that we consider it as something severe. */ if (timespec_after(&ts, &throttle_event_threshold)) cras_audio_thread_event_a2dp_throttle(); written = a2dp_write(&a2dpio->a2dp, cras_bt_transport_fd(a2dpio->transport), cras_bt_transport_write_mtu(a2dpio->transport)); ATLOG(atlog, AUDIO_THREAD_A2DP_WRITE, written, a2dp_queued_frames(&a2dpio->a2dp), 0); if (written == -EAGAIN) { /* If EAGAIN error lasts longer than 5 seconds, suspend the * a2dp connection. */ cras_bt_device_schedule_suspend(device, 5000, A2DP_LONG_TX_FAILURE); audio_thread_config_events_callback( cras_bt_transport_fd(a2dpio->transport), TRIGGER_POLL); return 0; } else if (written < 0) { /* Suspend a2dp immediately when receives error other than * EAGAIN. */ cras_bt_device_cancel_suspend(device); cras_bt_device_schedule_suspend(device, 0, A2DP_TX_FATAL_ERROR); /* Stop polling the socket in audio thread. Main thread will * close this iodev soon. */ audio_thread_config_events_callback( cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); return written; } /* Update the next flush time if one block successfully been written. */ if (written) add_timespecs(&a2dpio->next_flush_time, &a2dpio->flush_period); /* a2dp_write no longer return -EAGAIN when reaches here, disable * the polling write callback. */ audio_thread_config_events_callback( cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); /* Data succcessfully written to a2dp socket, cancel any scheduled * suspend timer. */ cras_bt_device_cancel_suspend(device); /* If it looks okay to write more and we do have queued data, try * encode more. But avoid the case when PCM buffer level is too close * to min_buffer_level so that another A2DP write could causes underrun. */ queued_frames = buf_queued(a2dpio->pcm_buf) / format_bytes; if (written && (iodev->min_buffer_level + a2dpio->write_block < queued_frames)) { err = encode_a2dp_packet(a2dpio); if (err < 0) return err; goto do_flush; } return 0; } static int delay_frames(const struct cras_iodev *iodev) { const struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; struct timespec tstamp; /* The number of frames in the pcm buffer plus two mtu packets */ return frames_queued(iodev, &tstamp) + a2dpio->sock_depth_frames; } static int get_buffer(struct cras_iodev *iodev, struct cras_audio_area **area, unsigned *frames) { size_t format_bytes; struct a2dp_io *a2dpio; a2dpio = (struct a2dp_io *)iodev; format_bytes = cras_get_format_bytes(iodev->format); if (iodev->direction != CRAS_STREAM_OUTPUT) return 0; *frames = MIN(*frames, buf_writable(a2dpio->pcm_buf) / format_bytes); iodev->area->frames = *frames; cras_audio_area_config_buf_pointers(iodev->area, iodev->format, buf_write_pointer(a2dpio->pcm_buf)); *area = iodev->area; return 0; } static int put_buffer(struct cras_iodev *iodev, unsigned nwritten) { size_t written_bytes; size_t format_bytes; struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; format_bytes = cras_get_format_bytes(iodev->format); written_bytes = nwritten * format_bytes; if (written_bytes > buf_writable(a2dpio->pcm_buf)) return -EINVAL; buf_increment_write(a2dpio->pcm_buf, written_bytes); return encode_and_flush(iodev); } static int flush_buffer(struct cras_iodev *iodev) { return 0; } static void set_volume(struct cras_iodev *iodev) { size_t volume; struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; struct cras_bt_device *device = cras_bt_transport_device(a2dpio->transport); if (!cras_bt_device_get_use_hardware_volume(device)) return; volume = iodev->active_node->volume * 127 / 100; if (a2dpio->transport) cras_bt_transport_set_volume(a2dpio->transport, volume); } static void update_active_node(struct cras_iodev *iodev, unsigned node_idx, unsigned dev_enabled) { } void free_resources(struct a2dp_io *a2dpio) { struct cras_ionode *node; node = a2dpio->base.active_node; if (node) { cras_iodev_rm_node(&a2dpio->base, node); free(node); } free(a2dpio->base.supported_channel_counts); free(a2dpio->base.supported_rates); free(a2dpio->base.supported_formats); destroy_a2dp(&a2dpio->a2dp); } struct cras_iodev *a2dp_iodev_create(struct cras_bt_transport *transport) { int err; struct a2dp_io *a2dpio; struct cras_iodev *iodev; struct cras_ionode *node; a2dp_sbc_t a2dp; struct cras_bt_device *device; const char *name; a2dpio = (struct a2dp_io *)calloc(1, sizeof(*a2dpio)); if (!a2dpio) goto error; a2dpio->transport = transport; cras_bt_transport_configuration(a2dpio->transport, &a2dp, sizeof(a2dp)); err = init_a2dp(&a2dpio->a2dp, &a2dp); if (err) { syslog(LOG_ERR, "Fail to init a2dp"); goto error; } iodev = &a2dpio->base; /* A2DP only does output now */ iodev->direction = CRAS_STREAM_OUTPUT; /* Set iodev's name by bluetooth device's readable name, if * the readable name is not available, use address instead. */ device = cras_bt_transport_device(transport); name = cras_bt_device_name(device); if (!name) name = cras_bt_transport_object_path(a2dpio->transport); snprintf(iodev->info.name, sizeof(iodev->info.name), "%s", name); iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0'; iodev->info.stable_id = cras_bt_device_get_stable_id(device); iodev->configure_dev = configure_dev; iodev->frames_queued = frames_queued; iodev->delay_frames = delay_frames; iodev->get_buffer = get_buffer; iodev->put_buffer = put_buffer; iodev->flush_buffer = flush_buffer; iodev->no_stream = no_stream; iodev->output_underrun = output_underrun; iodev->close_dev = close_dev; iodev->update_supported_formats = update_supported_formats; iodev->update_active_node = update_active_node; iodev->set_volume = set_volume; iodev->start = start; iodev->frames_to_play_in_sleep = frames_to_play_in_sleep; /* Create an empty ionode */ node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; strcpy(node->name, iodev->info.name); node->plugged = 1; node->type = CRAS_NODE_TYPE_BLUETOOTH; node->volume = 100; gettimeofday(&node->plugged_time, NULL); /* Prepare active node before append, so bt_io can extract correct * info from A2DP iodev and node. */ cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); cras_bt_device_append_iodev( device, iodev, cras_bt_transport_profile(a2dpio->transport)); /* Record max supported channels into cras_iodev_info. */ iodev->info.max_supported_channels = (a2dp.channel_mode == SBC_CHANNEL_MODE_MONO) ? 1 : 2; ewma_power_disable(&iodev->ewma); return iodev; error: if (a2dpio) { free_resources(a2dpio); free(a2dpio); } return NULL; } void a2dp_iodev_destroy(struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; struct cras_bt_device *device; a2dpio->destroyed = 1; device = cras_bt_transport_device(a2dpio->transport); /* A2DP does output only */ cras_bt_device_rm_iodev(device, iodev); /* Free resources when device successfully removed. */ free_resources(a2dpio); cras_iodev_free_resources(iodev); free(a2dpio); }