[pulseaudio-discuss] [PATCH] alsa: get avail, delay, timestamps in a single kernel call

David Henningsson david.henningsson at canonical.com
Tue Nov 6 23:40:28 PST 2012


On 11/05/2012 10:35 PM, Pierre-Louis Bossart wrote:
>
>> sorry for the long delay.
>
> no worries. looks like this mailing list went back 4 months in time with
> the switch from Daylight Savings time?

Naah, we more decided that there were a few things we wanted to review 
for 3.0 and this was one of them :-)

>> This seems to make a lot of sense, but a question - does this impose a
>> requirement on a certain version of alsa-lib and/or the linux kernel?
>
> no, these changes are using standard calls.
> The changes I pushed at the kernel level since my presentation at the
> Plumbers conference will require a specific version of alsa-lib to read
> the audio timestamps, everything below should work right off the bat
> without dependencies.

Ok. I took your patch for a small test spin and it didn't seem to have 
broken anything, so I pushed this patch now. Thanks for your contribution!

>
>> 2012-07-30 02:46, Pierre-Louis Bossart skrev:
>>> Refactor code to fetch avail, delay and timestamp values
>>> in a single call to snd_pcm_status().
>>> The information reported is exactly the same as before,
>>> however it is extracted in a more atomic manner to
>>> improve timer-based scheduling.
>>>
>>> Signed-off-by: Pierre-Louis Bossart
>>> <pierre-louis.bossart at linux.intel.com>
>>> ---
>>>   src/modules/alsa/alsa-sink.c   |   12 ++++--------
>>>   src/modules/alsa/alsa-source.c |   12 ++++--------
>>>   src/modules/alsa/alsa-util.c   |   17 ++++++++++++-----
>>>   src/modules/alsa/alsa-util.h   |    2 +-
>>>   4 files changed, 21 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
>>> index 544399e..e4baa1f 100644
>>> --- a/src/modules/alsa/alsa-sink.c
>>> +++ b/src/modules/alsa/alsa-sink.c
>>> @@ -825,6 +825,7 @@ static void update_smoother(struct userdata *u) {
>>>       int err;
>>>       pa_usec_t now1 = 0, now2;
>>>       snd_pcm_status_t *status;
>>> +    snd_htimestamp_t htstamp = { 0, 0 };
>>>       snd_pcm_status_alloca(&status);
>>> @@ -833,18 +834,13 @@ static void update_smoother(struct userdata *u) {
>>>       /* Let's update the time smoother */
>>> -    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay,
>>> u->hwbuf_size, &u->sink->sample_spec, FALSE)) < 0)) {
>>> +    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, status,
>>> &delay, u->hwbuf_size, &u->sink->sample_spec, FALSE)) < 0)) {
>>>           pa_log_warn("Failed to query DSP status data: %s",
>>> pa_alsa_strerror(err));
>>>           return;
>>>       }
>>> -    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0))
>>> -        pa_log_warn("Failed to get timestamp: %s",
>>> pa_alsa_strerror(err));
>>> -    else {
>>> -        snd_htimestamp_t htstamp = { 0, 0 };
>>> -        snd_pcm_status_get_htstamp(status, &htstamp);
>>> -        now1 = pa_timespec_load(&htstamp);
>>> -    }
>>> +    snd_pcm_status_get_htstamp(status, &htstamp);
>>> +    now1 = pa_timespec_load(&htstamp);
>>>       /* Hmm, if the timestamp is 0, then it wasn't set and we take
>>> the current time */
>>>       if (now1 <= 0)
>>> diff --git a/src/modules/alsa/alsa-source.c
>>> b/src/modules/alsa/alsa-source.c
>>> index 94d4a09..17566e7 100644
>>> --- a/src/modules/alsa/alsa-source.c
>>> +++ b/src/modules/alsa/alsa-source.c
>>> @@ -767,6 +767,7 @@ static void update_smoother(struct userdata *u) {
>>>       int err;
>>>       pa_usec_t now1 = 0, now2;
>>>       snd_pcm_status_t *status;
>>> +    snd_htimestamp_t htstamp = { 0, 0 };
>>>       snd_pcm_status_alloca(&status);
>>> @@ -775,18 +776,13 @@ static void update_smoother(struct userdata *u) {
>>>       /* Let's update the time smoother */
>>> -    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay,
>>> u->hwbuf_size, &u->source->sample_spec, TRUE)) < 0)) {
>>> +    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, status,
>>> &delay, u->hwbuf_size, &u->source->sample_spec, TRUE)) < 0)) {
>>>           pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err));
>>>           return;
>>>       }
>>> -    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0))
>>> -        pa_log_warn("Failed to get timestamp: %s",
>>> pa_alsa_strerror(err));
>>> -    else {
>>> -        snd_htimestamp_t htstamp = { 0, 0 };
>>> -        snd_pcm_status_get_htstamp(status, &htstamp);
>>> -        now1 = pa_timespec_load(&htstamp);
>>> -    }
>>> +    snd_pcm_status_get_htstamp(status, &htstamp);
>>> +    now1 = pa_timespec_load(&htstamp);
>>>       /* Hmm, if the timestamp is 0, then it wasn't set and we take
>>> the current time */
>>>       if (now1 <= 0)
>>> diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
>>> index bb4e307..4a29a9a 100644
>>> --- a/src/modules/alsa/alsa-util.c
>>> +++ b/src/modules/alsa/alsa-util.c
>>> @@ -1141,10 +1141,11 @@ snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t
>>> *pcm, size_t hwbuf_size, const pa
>>>       return n;
>>>   }
>>> -int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay,
>>> size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture) {
>>> +int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status,
>>> snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss,
>>> +                       pa_bool_t capture) {
>>>       ssize_t k;
>>>       size_t abs_k;
>>> -    int r;
>>> +    int err;
>>>       snd_pcm_sframes_t avail = 0;
>>>       pa_assert(pcm);
>>> @@ -1154,10 +1155,16 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm,
>>> snd_pcm_sframes_t *delay, size_t hwbuf_si
>>>       /* Some ALSA driver expose weird bugs, let's inform the user about
>>>        * what is going on. We're going to get both the avail and delay
>>> values so
>>> -     * that we can compare and check them for capture */
>>> +     * that we can compare and check them for capture.
>>> +     * This is done with snd_pcm_status() which provides
>>> +     * avail, delay and timestamp values in a single kernel call to
>>> improve
>>> +     * timer-based scheduling */
>>> -    if ((r = snd_pcm_avail_delay(pcm, &avail, delay)) < 0)
>>> -        return r;
>>> +    if ((err = snd_pcm_status(pcm, status)) < 0)
>>> +        return err;
>>> +
>>> +    avail = snd_pcm_status_get_avail(status);
>>> +    *delay = snd_pcm_status_get_delay(status);
>>>       k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
>>> diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
>>> index a4beed2..236a329 100644
>>> --- a/src/modules/alsa/alsa-util.h
>>> +++ b/src/modules/alsa/alsa-util.h
>>> @@ -125,7 +125,7 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int
>>> revents);
>>>   pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll
>>> *rtpoll);
>>>   snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t
>>> hwbuf_size, const pa_sample_spec *ss);
>>> -int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay,
>>> size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture);
>>> +int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status,
>>> snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss,
>>> pa_bool_t capture);
>>>   int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const
>>> snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset,
>>> snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss);
>>>   char *pa_alsa_get_driver_name(int card);
>>
>>
>



-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list