From nobody Sun Jan 25 12:01:05 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1769155112; cv=none; d=zohomail.com; s=zohoarc; b=e5O4FM1KviR8m2kEwnqHE5Rxzdg1UGIH5nayD8PKGzIWGpAAkzo+e0ZaEALGNOaI32/yD2RhTlxv9ljs7kxuHcQM1bpOg5lsHPLAsumy0r9gdJymq/WFmcYH5GkTZSgJjVpjpL67/Seg7u4d5LWh8vD07P43YEftPGVeqW1Wnsg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769155112; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WZzqV/cRFWzcsw5CR+s7vRaX0P+9uO+clQOhMcaSI3c=; b=lbbhIDSvcer9gZJRH4uSzgKvPeOoMo0rbgoUvj4po8/2LoagGws+5YUe0l1HbByLRVCOs1teGr0G3RFSujcSRcY4xvWNbyZwIqM4cUpCk/eTWM9IAiKID4Bk0zM3jewhsFfG7pyLqATEmegZ32iQrB5pCuhAwbYLdRXWzOPKGmI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769155112366570.1126589540585; Thu, 22 Jan 2026 23:58:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vjBzH-0007H7-0k; Fri, 23 Jan 2026 02:53:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjByR-0006LJ-Mv for qemu-devel@nongnu.org; Fri, 23 Jan 2026 02:52:58 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjByO-0002Fm-JY for qemu-devel@nongnu.org; Fri, 23 Jan 2026 02:52:54 -0500 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-373-I74LuPFlMiurxg16vMHhPg-1; Fri, 23 Jan 2026 02:52:48 -0500 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7B4E51944EBB; Fri, 23 Jan 2026 07:52:47 +0000 (UTC) Received: from localhost (unknown [10.45.242.5]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 791501800285; Fri, 23 Jan 2026 07:52:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769154771; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WZzqV/cRFWzcsw5CR+s7vRaX0P+9uO+clQOhMcaSI3c=; b=CyuaurdJCDikKN6BbR6ZYmnbs8Tv+vpOOT0P82LU/y73lFxThTjWnV05Qef3sD8IYywtr4 rSA6cI/U/qn89O2aIjrTvk/Ix6bTTdHel8/znr7EEfHYgQAKHARVyf3Cm3pm6mHM1clX8Y +tHamCvABuLR1N8GI6B/USvwm8matkQ= X-MC-Unique: I74LuPFlMiurxg16vMHhPg-1 X-Mimecast-MFC-AGG-ID: I74LuPFlMiurxg16vMHhPg_1769154767 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH 29/37] replay: remove dependency on audio/ Date: Fri, 23 Jan 2026 11:49:32 +0400 Message-ID: <20260123074945.2563196-30-marcandre.lureau@redhat.com> In-Reply-To: <20260123074945.2563196-1-marcandre.lureau@redhat.com> References: <20260123074945.2563196-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 12 X-Spam_score: 1.2 X-Spam_bar: + X-Spam_report: (1.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.07, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1769155114939154100 From: Marc-Andr=C3=A9 Lureau The replay infrastructure shouldn't depend on internals of audio/. (st_sample is an internal implementation detail and could be different) Let audio drive the audio samples recording/replaying. Notice also we don't need to save & restore the internal ring "wpos", all replay should care about is the number of samples and the samples. Bump the replay version. Signed-off-by: Marc-Andr=C3=A9 Lureau --- audio/audio_int.h | 5 ++++ include/qemu/audio.h | 5 ---- include/system/replay.h | 11 +++++++-- replay/replay-internal.h | 2 ++ audio/audio.c | 23 ++++++++++++++++-- replay/replay-audio.c | 51 +++++++++++++++++++++++---------------- replay/replay.c | 2 +- replay/stubs-system.c | 8 +++++- tests/audio/audio-stubs.c | 13 +++++++--- 9 files changed, 85 insertions(+), 35 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index e1f9fa333ba..250fd45238d 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -309,6 +309,11 @@ static inline size_t audio_ring_posb(size_t pos, size_= t dist, size_t len) AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); =20 +void audio_sample_to_uint64(const st_sample *sample, int pos, + uint64_t *left, uint64_t *right); +void audio_sample_from_uint64(st_sample *sample, int pos, + uint64_t left, uint64_t right); + #define TYPE_AUDIO_MIXENG_BACKEND "audio-mixeng-backend" OBJECT_DECLARE_TYPE(AudioMixengBackend, AudioMixengBackendClass, AUDIO_MIX= ENG_BACKEND) =20 diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 1eeead2a722..03ce9adbc88 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -120,11 +120,6 @@ void audio_cleanup(void); =20 typedef struct st_sample st_sample; =20 -void audio_sample_to_uint64(const st_sample *sample, int pos, - uint64_t *left, uint64_t *right); -void audio_sample_from_uint64(st_sample *sample, int pos, - uint64_t left, uint64_t right); - void audio_add_audiodev(Audiodev *audio); void audio_add_default_audiodev(Audiodev *dev, Error **errp); void audio_parse_option(const char *opt); diff --git a/include/system/replay.h b/include/system/replay.h index f8715ca9feb..19fb6dbb396 100644 --- a/include/system/replay.h +++ b/include/system/replay.h @@ -165,8 +165,15 @@ void replay_net_packet_event(ReplayNetState *rns, unsi= gned flags, =20 /*! Saves/restores number of played samples of audio out operation. */ void replay_audio_out(size_t *played); -/*! Saves/restores recorded samples of audio in operation. */ -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size); +/* + * Start saves/restores recorded samples of audio in operation. + * Must be called before replay_audio_in_sample_lr(). + */ +void replay_audio_in_start(size_t *recorded); +/* Saves/restores recorded samples. */ +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right); +/* Finish saves/restores recorded samples. */ +void replay_audio_in_finish(void); =20 /* VM state operations */ =20 diff --git a/replay/replay-internal.h b/replay/replay-internal.h index 75249b76936..643b357da12 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -85,6 +85,7 @@ enum ReplayEvents { * @file_offset: offset into replay log at replay snapshot * @block_request_id: current serialised block request id * @read_event_id: current async read event id + * @n_audio_samples: expected audio samples */ typedef struct ReplayState { int64_t cached_clock[REPLAY_CLOCK_COUNT]; @@ -96,6 +97,7 @@ typedef struct ReplayState { uint64_t file_offset; uint64_t block_request_id; uint64_t read_event_id; + size_t n_audio_samples; } ReplayState; extern ReplayState replay_state; =20 diff --git a/audio/audio.c b/audio/audio.c index b303cfb4904..a03ca397d33 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1300,13 +1300,32 @@ static void audio_run_in(AudioMixengBackend *s) while ((hw =3D audio_pcm_hw_find_any_enabled_in(s, hw))) { SWVoiceIn *sw; size_t captured =3D 0, min; + int pos; =20 if (replay_mode !=3D REPLAY_MODE_PLAY) { captured =3D audio_pcm_hw_run_in( hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw)); } - replay_audio_in(&captured, hw->conv_buf.buffer, &hw->conv_buf.pos, - hw->conv_buf.size); + + replay_audio_in_start(&captured); + assert(captured <=3D hw->conv_buf.size); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + hw->conv_buf.pos =3D (hw->conv_buf.pos + captured) % hw->conv_= buf.size; + } + for (pos =3D (hw->conv_buf.pos - captured + hw->conv_buf.size) % h= w->conv_buf.size; + pos !=3D hw->conv_buf.pos; + pos =3D (pos + 1) % hw->conv_buf.size) { + uint64_t left, right; + + if (replay_mode =3D=3D REPLAY_MODE_RECORD) { + audio_sample_to_uint64(hw->conv_buf.buffer, pos, &left= , &right); + } + replay_audio_in_sample_lr(&left, &right); + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + audio_sample_from_uint64(hw->conv_buf.buffer, pos, lef= t, right); + } + } + replay_audio_in_finish(); =20 min =3D audio_pcm_hw_find_min_in (hw); hw->total_samples_captured +=3D captured - min; diff --git a/replay/replay-audio.c b/replay/replay-audio.c index 1b614f41379..7d20ae9110c 100644 --- a/replay/replay-audio.c +++ b/replay/replay-audio.c @@ -13,7 +13,6 @@ #include "qemu/error-report.h" #include "system/replay.h" #include "replay-internal.h" -#include "qemu/audio.h" =20 void replay_audio_out(size_t *played) { @@ -35,38 +34,48 @@ void replay_audio_out(size_t *played) } } =20 -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size) +void replay_audio_in_start(size_t *nsamples) { - int pos; - uint64_t left, right; if (replay_mode =3D=3D REPLAY_MODE_RECORD) { g_assert(replay_mutex_locked()); replay_save_instructions(); replay_put_event(EVENT_AUDIO_IN); - replay_put_qword(*recorded); - replay_put_qword(*wpos); - for (pos =3D (*wpos - *recorded + size) % size ; pos !=3D *wpos - ; pos =3D (pos + 1) % size) { - audio_sample_to_uint64(samples, pos, &left, &right); - replay_put_qword(left); - replay_put_qword(right); - } + replay_put_qword(*nsamples); + replay_state.n_audio_samples =3D *nsamples; } else if (replay_mode =3D=3D REPLAY_MODE_PLAY) { g_assert(replay_mutex_locked()); replay_account_executed_instructions(); if (replay_next_event_is(EVENT_AUDIO_IN)) { - *recorded =3D replay_get_qword(); - *wpos =3D replay_get_qword(); - for (pos =3D (*wpos - *recorded + size) % size ; pos !=3D *wpos - ; pos =3D (pos + 1) % size) { - left =3D replay_get_qword(); - right =3D replay_get_qword(); - audio_sample_from_uint64(samples, pos, left, right); - } - replay_finish_event(); + *nsamples =3D replay_get_qword(); + replay_state.n_audio_samples =3D *nsamples; } else { error_report("Missing audio in event in the replay log"); abort(); } } } + +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right) +{ + if (replay_mode =3D=3D REPLAY_MODE_RECORD) { + replay_put_qword(*left); + replay_put_qword(*right); + } else if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + *left =3D replay_get_qword(); + *right =3D replay_get_qword(); + } else { + return; + } + + assert(replay_state.n_audio_samples > 0); + replay_state.n_audio_samples--; +} + +void replay_audio_in_finish(void) +{ + assert(replay_state.n_audio_samples =3D=3D 0); + + if (replay_mode =3D=3D REPLAY_MODE_PLAY) { + replay_finish_event(); + } +} diff --git a/replay/replay.c b/replay/replay.c index b2121788c1d..2e5c6fa82ea 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -22,7 +22,7 @@ =20 /* Current version of the replay mechanism. Increase it when file format changes. */ -#define REPLAY_VERSION 0xe0200c +#define REPLAY_VERSION 0xe0200d /* Size of replay log header */ #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) =20 diff --git a/replay/stubs-system.c b/replay/stubs-system.c index 7f85764936f..b2c52bc4043 100644 --- a/replay/stubs-system.c +++ b/replay/stubs-system.c @@ -15,7 +15,13 @@ void replay_input_sync_event(void) void replay_add_blocker(const char *feature) { } -void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, s= ize_t size) +void replay_audio_in_start(size_t *nsamples) +{ +} +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right) +{ +} +void replay_audio_in_finish(void) { } void replay_audio_out(size_t *played) diff --git a/tests/audio/audio-stubs.c b/tests/audio/audio-stubs.c index 0bcdb6ce7a3..72bc08d116c 100644 --- a/tests/audio/audio-stubs.c +++ b/tests/audio/audio-stubs.c @@ -19,12 +19,19 @@ GQuark dbus_display_error_quark(void) return g_quark_from_static_string("dbus-display-error-quark"); } =20 -void replay_audio_in(size_t *recorded, st_sample *samples, - size_t *wpos, size_t size) +void replay_audio_out(size_t *played) { } =20 -void replay_audio_out(size_t *played) +void replay_audio_in_start(size_t *nsamples) +{ +} + +void replay_audio_in_sample_lr(uint64_t *left, uint64_t *right) +{ +} + +void replay_audio_in_finish(void) { } =20 --=20 2.52.0