From patchwork Fri Jul 8 15:03:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Young X-Patchwork-Id: 9221169 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D7BE060572 for ; Fri, 8 Jul 2016 15:03:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C6F0B28871 for ; Fri, 8 Jul 2016 15:03:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BB00E28875; Fri, 8 Jul 2016 15:03:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE,T_DKIM_INVALID autolearn=no version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B3E5D28871 for ; Fri, 8 Jul 2016 15:03:54 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 591EE266A99; Fri, 8 Jul 2016 17:03:52 +0200 (CEST) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id CAC282669BE; Fri, 8 Jul 2016 17:03:44 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 5557A266A14; Fri, 8 Jul 2016 17:03:43 +0200 (CEST) Received: from mail-pa0-f68.google.com (mail-pa0-f68.google.com [209.85.220.68]) by alsa0.perex.cz (Postfix) with ESMTP id 2BE5A265D85 for ; Fri, 8 Jul 2016 17:03:36 +0200 (CEST) Received: by mail-pa0-f68.google.com with SMTP id dx3so7685994pab.2 for ; Fri, 08 Jul 2016 08:03:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to; bh=7eXbUhYROYKbGPg+ZzNh9l8GAWbrDlksA0BtZNKhl+A=; b=K3+Lu7BEJOmnICMvvOwcXOjHQASA/63XAeGnBXGAMXsUKJeJ+Y2+xqqtWqNNRRYMqA 2MAKH5TWdXEW8jOcZ+C5FfXwbH169RQ0DGEj+nV+T2k4Y+6Q5il571wgiFHlJxfWs5LA BvHnbnEcwkYDBuabjR7qUmta+cFWNkD5b8FEIwJm1eNCN6HLyIGtYessE6jxbA7Ti0Pp 00bOhkLlqoc5MS6/72WurePBwiu3Iycvq4526DK5/lzmLkSBPxcfI+/DZZk0HZY/NyQJ puHxiYzw49RV4dWljnmOKgoBAFd2SAnQ5AeqBKBikga0B1GGkLDVpYLdNDMO2NcKV4TO Bh3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:subject:to:references:cc:from:message-id :date:user-agent:mime-version:in-reply-to; bh=7eXbUhYROYKbGPg+ZzNh9l8GAWbrDlksA0BtZNKhl+A=; b=jI+77xshCTWDtiNcprcFtH2WeWniyxtqssLdOYtmx1eNcNYNpPtWgb39dol8iGgz0K AUAK8MfscP2gbFGSTcWL7EnFqJDD2A9IxAK6F6x3A+ZdYEloeQYY49efeefcg/K3dB/9 Al/Df2hXtwzTSzUXQyfjiiwt1hRMZ49BdaaqwL71haOB9vaYRFhRJyDuOIZspUWqMhFT noTNXCwlzKBze6sjs76Hyb//UpYcIW6lF/axXctaZeM4Wp9W19rFOW7z9Ytkl5wA6rZO PaErlt5wLQ2HaODvSUkWDzjVaI2zisRvGqra4tSfLOzzKATkNIKDKH2YILJJe78Kmq8z PtKA== X-Gm-Message-State: ALyK8tJ2yGZ2SIE/XLrIMroI3HRLqY/CAF22TFrhSgzpTfqSYZsnWYUDAddfPySwDALs1w== X-Received: by 10.194.141.75 with SMTP id rm11mr6434125wjb.160.1467990214449; Fri, 08 Jul 2016 08:03:34 -0700 (PDT) Received: from [192.168.11.11] (45.143.6.51.dyn.plus.net. [51.6.143.45]) by smtp.googlemail.com with ESMTPSA id f193sm3451579wme.11.2016.07.08.08.03.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 Jul 2016 08:03:33 -0700 (PDT) To: Pierre-Louis Bossart , Takashi Iwai References: <5752A005.2050309@gmail.com> <5753FFF0.3050200@gmail.com> <57554591.20103@gmail.com> <51c7887a-db2f-ee88-8290-2f2d21d6435d@linux.intel.com> <57566D64.1050400@gmail.com> From: Alan Young Message-ID: <577FC0C4.1060508@IEE.org> Date: Fri, 8 Jul 2016 16:03:32 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <57566D64.1050400@gmail.com> X-Content-Filtered-By: Mailman/MimeDel 2.1.14 Cc: Raymond Yau , alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Improving status timestamp accuracy X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP On 07/06/16 07:44, Alan Young wrote: > I'll work on developing and testing a patch for consideration before > coming back to the last. It will be easier to discuss the merits or > otherwise of my proposal with a concrete, working patch to consider. Well, it has been a few weeks but this is what I have come up with. It is not perfect because of the issue noted in the comments but so far I have not been able to discover any downside. It many (most) cases, the reported delay (and audio_tstamp) is more accurate than it was before. In other cases there is no change. Alan. From 0c1378b8faa91e7bebf63a60ece3c5c942652a53 Mon Sep 17 00:00:00 2001 From: Alan Young Date: Fri, 8 Jul 2016 14:08:10 +0100 Subject: [PATCH] Improve accuracy of delay and audio_tstamp reporting. pcm_lib.c:snd_pcm_update_hw_ptr0() is responsible for updating the data used for various status reporting calls. Many drivers do not update the position upon a call to substream->ops->pointer() other then within an interrupt callback. Most drivers also do not update substream->runtime->delay (in the pointer() call) -- the main exception being USB drivers. Consequently reported delay and audio_tstamp values will, in these cases, be inaccurate by the time elapsed since the last interrupt callback. By recording the delay at the time of an interrupt callback, and the timestamp at that time, the reported delay and audio_tstamp values can be adjusted to compensate for the time elapsed since the last interrupt. These adjustments are only made if the reported position or delay (as appropriate) have not changed since those recorded at the time of that interrupt. This approach fails if reported delay is adjusted to account from some data (such as the CODEC delay) but the position is not adjusted to the (probably more significant) current DMA offset. --- include/sound/pcm.h | 2 ++ sound/core/pcm_lib.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b0be092..55da224 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -417,6 +417,8 @@ struct snd_pcm_runtime { struct snd_pcm_audio_tstamp_config audio_tstamp_config; struct snd_pcm_audio_tstamp_report audio_tstamp_report; struct timespec driver_tstamp; + snd_pcm_sframes_t interrupt_delay; + struct timespec interrupt_tstamp; #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) /* -- OSS things -- */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 6b5a811..96cde4e 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -263,6 +263,12 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, audio_nsecs = div_u64(audio_frames * 1000000000LL, runtime->rate); *audio_tstamp = ns_to_timespec(audio_nsecs); + + if (!runtime->audio_tstamp_config.report_delay && runtime->interrupt_tstamp.tv_sec + && runtime->status->hw_ptr == runtime->hw_ptr_interrupt) { + struct timespec delta_time = timespec_sub(*curr_tstamp, runtime->interrupt_tstamp); + *audio_tstamp = timespec_add(*audio_tstamp, delta_time); + } } runtime->status->audio_tstamp = *audio_tstamp; runtime->status->tstamp = *curr_tstamp; @@ -275,6 +281,40 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, runtime->driver_tstamp = driver_tstamp; } +static void update_delay(struct snd_pcm_substream *substream, + struct timespec *curr_tstamp) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct timespec delta_time; + snd_pcm_sframes_t delta; + + /* Can only adjust the delay if we have base timestamp. */ + if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE || !runtime->interrupt_tstamp.tv_sec) + return; + + if (runtime->delay != runtime->interrupt_delay) { + /* + * Assume accurate if changed, + * which is not correct if driver supports variable + * codec delay reporting or similar + */ + return; + } + + delta_time = timespec_sub(*curr_tstamp, runtime->interrupt_tstamp); + delta = (delta_time.tv_sec * USEC_PER_SEC + delta_time.tv_nsec / NSEC_PER_USEC) + * runtime->rate / USEC_PER_SEC; + + /* sanity check */ + if (delta > runtime->period_size) + return; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->delay = runtime->interrupt_delay - delta; + else + runtime->delay = runtime->interrupt_delay + delta; +} + static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, unsigned int in_interrupt) { @@ -311,6 +351,11 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); } else snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); + + if (in_interrupt) { + runtime->interrupt_delay = runtime->delay; + runtime->interrupt_tstamp = curr_tstamp; + } } if (pos == SNDRV_PCM_POS_XRUN) { @@ -453,6 +498,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, } no_delta_check: + if (!in_interrupt && new_hw_ptr == runtime->hw_ptr_interrupt) { + update_delay(substream, &curr_tstamp); + } if (runtime->status->hw_ptr == new_hw_ptr) { update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); return 0; -- 2.5.5