qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

replay: add record/replay for audio passthrough

This patch adds recording and replaying audio data. Is saves synchronization
information for audio out and inputs from the microphone.

v2: removed unneeded whitespace change

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-id: 20170202055054.4848.94901.stgit@PASHA-ISP.lan02.inno

[ kraxel: add qemu/error-report.h include to fix osx build failure ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Pavel Dovgalyuk and committed by
Gerd Hoffmann
3d4d16f4 e7c83a88

+142 -2
+7 -2
audio/audio.c
··· 28 28 #include "qemu/timer.h" 29 29 #include "sysemu/sysemu.h" 30 30 #include "qemu/cutils.h" 31 + #include "sysemu/replay.h" 31 32 32 33 #define AUDIO_CAP "audio" 33 34 #include "audio_int.h" ··· 1387 1388 1388 1389 prev_rpos = hw->rpos; 1389 1390 played = hw->pcm_ops->run_out (hw, live); 1391 + replay_audio_out(&played); 1390 1392 if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) { 1391 1393 dolog ("hw->rpos=%d hw->samples=%d played=%d\n", 1392 1394 hw->rpos, hw->samples, played); ··· 1450 1452 1451 1453 while ((hw = audio_pcm_hw_find_any_enabled_in (hw))) { 1452 1454 SWVoiceIn *sw; 1453 - int captured, min; 1455 + int captured = 0, min; 1454 1456 1455 - captured = hw->pcm_ops->run_in (hw); 1457 + if (replay_mode != REPLAY_MODE_PLAY) { 1458 + captured = hw->pcm_ops->run_in(hw); 1459 + } 1460 + replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); 1456 1461 1457 1462 min = audio_pcm_hw_find_min_in (hw); 1458 1463 hw->total_samples_captured += captured - min;
+5
audio/audio.h
··· 166 166 bool audio_is_cleaning_up(void); 167 167 void audio_cleanup(void); 168 168 169 + void audio_sample_to_uint64(void *samples, int pos, 170 + uint64_t *left, uint64_t *right); 171 + void audio_sample_from_uint64(void *samples, int pos, 172 + uint64_t left, uint64_t right); 173 + 169 174 #endif /* QEMU_AUDIO_H */
+32
audio/mixeng.c
··· 25 25 #include "qemu/osdep.h" 26 26 #include "qemu-common.h" 27 27 #include "qemu/bswap.h" 28 + #include "qemu/error-report.h" 28 29 #include "audio.h" 29 30 30 31 #define AUDIO_CAP "mixeng" ··· 266 267 } 267 268 } 268 269 }; 270 + 271 + 272 + void audio_sample_to_uint64(void *samples, int pos, 273 + uint64_t *left, uint64_t *right) 274 + { 275 + struct st_sample *sample = samples; 276 + sample += pos; 277 + #ifdef FLOAT_MIXENG 278 + error_report( 279 + "Coreaudio and floating point samples are not supported by replay yet"); 280 + abort(); 281 + #else 282 + *left = sample->l; 283 + *right = sample->r; 284 + #endif 285 + } 286 + 287 + void audio_sample_from_uint64(void *samples, int pos, 288 + uint64_t left, uint64_t right) 289 + { 290 + struct st_sample *sample = samples; 291 + sample += pos; 292 + #ifdef FLOAT_MIXENG 293 + error_report( 294 + "Coreaudio and floating point samples are not supported by replay yet"); 295 + abort(); 296 + #else 297 + sample->l = left; 298 + sample->r = right; 299 + #endif 300 + } 269 301 270 302 /* 271 303 * August 21, 1998
+7
docs/replay.txt
··· 225 225 the outer world into the log. In replay mode packets from the log are 226 226 injected into the network device. All interactions with network backend 227 227 in replay mode are disabled. 228 + 229 + Audio devices 230 + ------------- 231 + 232 + Audio data is recorded and replay automatically. The command line for recording 233 + and replaying must contain identical specifications of audio hardware, e.g.: 234 + -soundhw ac97
+7
include/sysemu/replay.h
··· 152 152 void replay_net_packet_event(ReplayNetState *rns, unsigned flags, 153 153 const struct iovec *iov, int iovcnt); 154 154 155 + /* Audio */ 156 + 157 + /*! Saves/restores number of played samples of audio out operation. */ 158 + void replay_audio_out(int *played); 159 + /*! Saves/restores recorded samples of audio in operation. */ 160 + void replay_audio_in(int *recorded, void *samples, int *wpos, int size); 161 + 155 162 /* VM state operations */ 156 163 157 164 /*! Called at the start of execution.
+1
replay/Makefile.objs
··· 6 6 common-obj-y += replay-char.o 7 7 common-obj-y += replay-snapshot.o 8 8 common-obj-y += replay-net.o 9 + common-obj-y += replay-audio.o
+79
replay/replay-audio.c
··· 1 + /* 2 + * replay-audio.c 3 + * 4 + * Copyright (c) 2010-2017 Institute for System Programming 5 + * of the Russian Academy of Sciences. 6 + * 7 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 + * See the COPYING file in the top-level directory. 9 + * 10 + */ 11 + 12 + #include "qemu/osdep.h" 13 + #include "qemu/error-report.h" 14 + #include "sysemu/replay.h" 15 + #include "replay-internal.h" 16 + #include "sysemu/sysemu.h" 17 + #include "audio/audio.h" 18 + 19 + void replay_audio_out(int *played) 20 + { 21 + if (replay_mode == REPLAY_MODE_RECORD) { 22 + replay_save_instructions(); 23 + replay_mutex_lock(); 24 + replay_put_event(EVENT_AUDIO_OUT); 25 + replay_put_dword(*played); 26 + replay_mutex_unlock(); 27 + } else if (replay_mode == REPLAY_MODE_PLAY) { 28 + replay_account_executed_instructions(); 29 + replay_mutex_lock(); 30 + if (replay_next_event_is(EVENT_AUDIO_OUT)) { 31 + *played = replay_get_dword(); 32 + replay_finish_event(); 33 + replay_mutex_unlock(); 34 + } else { 35 + replay_mutex_unlock(); 36 + error_report("Missing audio out event in the replay log"); 37 + abort(); 38 + } 39 + } 40 + } 41 + 42 + void replay_audio_in(int *recorded, void *samples, int *wpos, int size) 43 + { 44 + int pos; 45 + uint64_t left, right; 46 + if (replay_mode == REPLAY_MODE_RECORD) { 47 + replay_save_instructions(); 48 + replay_mutex_lock(); 49 + replay_put_event(EVENT_AUDIO_IN); 50 + replay_put_dword(*recorded); 51 + replay_put_dword(*wpos); 52 + for (pos = (*wpos - *recorded + size) % size ; pos != *wpos 53 + ; pos = (pos + 1) % size) { 54 + audio_sample_to_uint64(samples, pos, &left, &right); 55 + replay_put_qword(left); 56 + replay_put_qword(right); 57 + } 58 + replay_mutex_unlock(); 59 + } else if (replay_mode == REPLAY_MODE_PLAY) { 60 + replay_account_executed_instructions(); 61 + replay_mutex_lock(); 62 + if (replay_next_event_is(EVENT_AUDIO_IN)) { 63 + *recorded = replay_get_dword(); 64 + *wpos = replay_get_dword(); 65 + for (pos = (*wpos - *recorded + size) % size ; pos != *wpos 66 + ; pos = (pos + 1) % size) { 67 + left = replay_get_qword(); 68 + right = replay_get_qword(); 69 + audio_sample_from_uint64(samples, pos, left, right); 70 + } 71 + replay_finish_event(); 72 + replay_mutex_unlock(); 73 + } else { 74 + replay_mutex_unlock(); 75 + error_report("Missing audio in event in the replay log"); 76 + abort(); 77 + } 78 + } 79 + }
+4
replay/replay-internal.h
··· 29 29 /* for character device read all event */ 30 30 EVENT_CHAR_READ_ALL, 31 31 EVENT_CHAR_READ_ALL_ERROR, 32 + /* for audio out event */ 33 + EVENT_AUDIO_OUT, 34 + /* for audio in event */ 35 + EVENT_AUDIO_IN, 32 36 /* for clock read/writes */ 33 37 /* some of greater codes are reserved for clocks */ 34 38 EVENT_CLOCK,