mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
bluetooth: apply write MTU detection based on read packet size
HFP Audio Connection SCO configuration is negotiated symmetrically in both directions, and USB HCI SCO packet framing is also symmetric in both directions. This means that packet size will be the same for reads and writes over HFP SCO socket. HFP profile specification states that valid speech data shall exist on the Synchronous Connection in both directions after the Audio Connection is established. This guarantees that an incoming packet will arrive shortly after SCO connection is established. Use it's size to fix write MTU in case kernel value is wrong. Discussion here https://lore.kernel.org/patchwork/patch/1303411/ Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/507>
This commit is contained in:
parent
4444ecad6f
commit
62776cc815
4 changed files with 22 additions and 0 deletions
|
|
@ -365,6 +365,10 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
|
||||||
|
|
||||||
pa_assert(t);
|
pa_assert(t);
|
||||||
|
|
||||||
|
/* since SCO setup is symmetric, fix write MTU to be size of last read packet */
|
||||||
|
if (t->last_read_size)
|
||||||
|
write_mtu = PA_MIN(t->last_read_size, write_mtu);
|
||||||
|
|
||||||
/* if encoder buffer has less data than required to make complete packet */
|
/* if encoder buffer has less data than required to make complete packet */
|
||||||
if (size < write_mtu)
|
if (size < write_mtu)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -386,6 +390,11 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
|
||||||
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
|
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
|
||||||
/* Drain write buffer */
|
/* Drain write buffer */
|
||||||
written = size;
|
written = size;
|
||||||
|
} else if (errno == EINVAL && t->last_read_size == 0) {
|
||||||
|
/* Likely write_link_mtu is still wrong, retry after next successful read */
|
||||||
|
pa_log_debug("got write EINVAL, next successful read should fix MTU");
|
||||||
|
/* Drain write buffer */
|
||||||
|
written = size;
|
||||||
} else {
|
} else {
|
||||||
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
|
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
|
||||||
/* Report error from write call */
|
/* Report error from write call */
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,10 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
|
||||||
|
|
||||||
pa_assert(t);
|
pa_assert(t);
|
||||||
|
|
||||||
|
/* since SCO setup is symmetric, fix write MTU to be size of last read packet */
|
||||||
|
if (t->last_read_size)
|
||||||
|
write_mtu = PA_MIN(t->last_read_size, write_mtu);
|
||||||
|
|
||||||
/* if encoder buffer has less data than required to make complete packet */
|
/* if encoder buffer has less data than required to make complete packet */
|
||||||
if (size < write_mtu)
|
if (size < write_mtu)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -111,6 +115,11 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
|
||||||
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
|
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
|
||||||
/* Drain write buffer */
|
/* Drain write buffer */
|
||||||
written = size;
|
written = size;
|
||||||
|
} else if (errno == EINVAL && t->last_read_size == 0) {
|
||||||
|
/* Likely write_link_mtu is still wrong, retry after next successful read */
|
||||||
|
pa_log_debug("got write EINVAL, next successful read should fix MTU");
|
||||||
|
/* Drain write buffer */
|
||||||
|
written = size;
|
||||||
} else {
|
} else {
|
||||||
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
|
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
|
||||||
/* Report error from write call */
|
/* Report error from write call */
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ struct pa_bluetooth_transport {
|
||||||
|
|
||||||
const pa_a2dp_codec *bt_codec;
|
const pa_a2dp_codec *bt_codec;
|
||||||
int stream_write_type;
|
int stream_write_type;
|
||||||
|
size_t last_read_size;
|
||||||
|
|
||||||
pa_volume_t source_volume;
|
pa_volume_t source_volume;
|
||||||
pa_volume_t sink_volume;
|
pa_volume_t sink_volume;
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,9 @@ static ssize_t bt_transport_read(pa_bluetooth_transport *t, int fd, void *buffer
|
||||||
|
|
||||||
pa_assert((size_t) received <= size);
|
pa_assert((size_t) received <= size);
|
||||||
|
|
||||||
|
/* allow write side to find out size of last read packet */
|
||||||
|
t->last_read_size = received;
|
||||||
|
|
||||||
if (p_timestamp) {
|
if (p_timestamp) {
|
||||||
/* TODO: get timestamp from rtp */
|
/* TODO: get timestamp from rtp */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue