[v11,03/11] bluetooth: Implement reading SO_TIMESTAMP for A2DP source

Submitted by Pali Rohár on June 2, 2019, 3:25 p.m.

Details

Message ID 20190602152520.2935-4-pali.rohar@gmail.com
State New
Headers show
Series "New API for Bluetooth A2DP codecs" ( rev: 84 83 82 81 80 79 78 77 76 75 74 ) in PulseAudio

Not browsing as part of any series.

Commit Message

Pali Rohár June 2, 2019, 3:25 p.m.
---
 src/modules/bluetooth/module-bluez5-device.c | 31 ++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index c0b293d94..e79d472bc 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -536,6 +536,10 @@  static int a2dp_process_push(struct userdata *u) {
     memchunk.index = memchunk.length = 0;
 
     for (;;) {
+        uint8_t aux[1024];
+        struct iovec iov;
+        struct cmsghdr *cm;
+        struct msghdr m;
         bool found_tstamp = false;
         pa_usec_t tstamp;
         uint8_t *ptr;
@@ -544,7 +548,19 @@  static int a2dp_process_push(struct userdata *u) {
 
         a2dp_prepare_decoder_buffer(u);
 
-        l = pa_read(u->stream_fd, u->decoder_buffer, u->read_encoded_block_size, &u->stream_write_type);
+        pa_zero(m);
+        pa_zero(aux);
+        pa_zero(iov);
+
+        m.msg_iov = &iov;
+        m.msg_iovlen = 1;
+        m.msg_control = aux;
+        m.msg_controllen = sizeof(aux);
+
+        iov.iov_base = u->decoder_buffer;
+        iov.iov_len = u->read_encoded_block_size;
+
+        l = recvmsg(u->stream_fd, &m, 0);
 
         if (l <= 0) {
 
@@ -564,8 +580,19 @@  static int a2dp_process_push(struct userdata *u) {
         pa_assert((size_t) l <= u->decoder_buffer_size);
 
         /* TODO: get timestamp from rtp */
+
+        for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
+            if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
+                struct timeval *tv = (struct timeval*) CMSG_DATA(cm);
+                pa_rtclock_from_wallclock(tv);
+                tstamp = pa_timeval_load(tv);
+                found_tstamp = true;
+                break;
+            }
+        }
+
         if (!found_tstamp) {
-            /* pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); */
+            pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");
             tstamp = pa_rtclock_now();
         }
 

Comments

On Sun, 2019-06-02 at 17:25 +0200, Pali Rohár wrote:
> ---
>  src/modules/bluetooth/module-bluez5-device.c | 31 ++++++++++++++++++++++++++--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
> index c0b293d94..e79d472bc 100644
> --- a/src/modules/bluetooth/module-bluez5-device.c
> +++ b/src/modules/bluetooth/module-bluez5-device.c
> @@ -536,6 +536,10 @@ static int a2dp_process_push(struct userdata *u) {
>      memchunk.index = memchunk.length = 0;
>  
>      for (;;) {
> +        uint8_t aux[1024];
> +        struct iovec iov;
> +        struct cmsghdr *cm;
> +        struct msghdr m;
>          bool found_tstamp = false;
>          pa_usec_t tstamp;
>          uint8_t *ptr;
> @@ -544,7 +548,19 @@ static int a2dp_process_push(struct userdata *u) {
>  
>          a2dp_prepare_decoder_buffer(u);
>  
> -        l = pa_read(u->stream_fd, u->decoder_buffer, u->read_encoded_block_size, &u->stream_write_type);
> +        pa_zero(m);
> +        pa_zero(aux);
> +        pa_zero(iov);
> +
> +        m.msg_iov = &iov;
> +        m.msg_iovlen = 1;
> +        m.msg_control = aux;
> +        m.msg_controllen = sizeof(aux);
> +
> +        iov.iov_base = u->decoder_buffer;
> +        iov.iov_len = u->read_encoded_block_size;
> +
> +        l = recvmsg(u->stream_fd, &m, 0);
>  
>          if (l <= 0) {
>  
> @@ -564,8 +580,19 @@ static int a2dp_process_push(struct userdata *u) {
>          pa_assert((size_t) l <= u->decoder_buffer_size);
>  
>          /* TODO: get timestamp from rtp */
> +
> +        for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
> +            if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
> +                struct timeval *tv = (struct timeval*) CMSG_DATA(cm);
> +                pa_rtclock_from_wallclock(tv);
> +                tstamp = pa_timeval_load(tv);
> +                found_tstamp = true;
> +                break;
> +            }
> +        }
> +
>          if (!found_tstamp) {
> -            /* pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); */
> +            pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");

If SO_TIMESTAMP isn't set on one message, it's probably not set on any
message. Flooding the log isn't good, so this needs some rework. Maybe
PA_ONCE_BEGIN/END would be appropriate here?
On Monday 17 June 2019 12:36:52 Tanu Kaskinen wrote:
> On Sun, 2019-06-02 at 17:25 +0200, Pali Rohár wrote:
> > ---
> >  src/modules/bluetooth/module-bluez5-device.c | 31 ++++++++++++++++++++++++++--
> >  1 file changed, 29 insertions(+), 2 deletions(-)
> > 
> > diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
> > index c0b293d94..e79d472bc 100644
> > --- a/src/modules/bluetooth/module-bluez5-device.c
> > +++ b/src/modules/bluetooth/module-bluez5-device.c
> > @@ -536,6 +536,10 @@ static int a2dp_process_push(struct userdata *u) {
> >      memchunk.index = memchunk.length = 0;
> >  
> >      for (;;) {
> > +        uint8_t aux[1024];
> > +        struct iovec iov;
> > +        struct cmsghdr *cm;
> > +        struct msghdr m;
> >          bool found_tstamp = false;
> >          pa_usec_t tstamp;
> >          uint8_t *ptr;
> > @@ -544,7 +548,19 @@ static int a2dp_process_push(struct userdata *u) {
> >  
> >          a2dp_prepare_decoder_buffer(u);
> >  
> > -        l = pa_read(u->stream_fd, u->decoder_buffer, u->read_encoded_block_size, &u->stream_write_type);
> > +        pa_zero(m);
> > +        pa_zero(aux);
> > +        pa_zero(iov);
> > +
> > +        m.msg_iov = &iov;
> > +        m.msg_iovlen = 1;
> > +        m.msg_control = aux;
> > +        m.msg_controllen = sizeof(aux);
> > +
> > +        iov.iov_base = u->decoder_buffer;
> > +        iov.iov_len = u->read_encoded_block_size;
> > +
> > +        l = recvmsg(u->stream_fd, &m, 0);
> >  
> >          if (l <= 0) {
> >  
> > @@ -564,8 +580,19 @@ static int a2dp_process_push(struct userdata *u) {
> >          pa_assert((size_t) l <= u->decoder_buffer_size);
> >  
> >          /* TODO: get timestamp from rtp */
> > +
> > +        for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
> > +            if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
> > +                struct timeval *tv = (struct timeval*) CMSG_DATA(cm);
> > +                pa_rtclock_from_wallclock(tv);
> > +                tstamp = pa_timeval_load(tv);
> > +                found_tstamp = true;
> > +                break;
> > +            }
> > +        }
> > +
> >          if (!found_tstamp) {
> > -            /* pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); */
> > +            pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");
> 
> If SO_TIMESTAMP isn't set on one message, it's probably not set on any
> message. Flooding the log isn't good, so this needs some rework. Maybe
> PA_ONCE_BEGIN/END would be appropriate here?

Same logic is already used in sco_process_push() function for HSP/HFP
profiles. I just reused it.

So fixing it should be done on more places.