qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Pavel Dovgalyuk" <dovgaluk@ispras.ru>
To: 'Pavel Dovgalyuk' <pavel.dovgaluk@ispras.ru>, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, kraxel@redhat.com
Subject: Re: [Qemu-devel] [PATCH] replay: add record/replay for audio passthrough
Date: Mon, 13 Feb 2017 08:04:54 +0300	[thread overview]
Message-ID: <000e01d285b6$b7073290$251597b0$@ru> (raw)
In-Reply-To: <20170131115926.7132.9645.stgit@PASHA-ISP>

Ping?

Pavel Dovgalyuk


> -----Original Message-----
> From: Pavel Dovgalyuk [mailto:pavel.dovgaluk@ispras.ru]
> Sent: Tuesday, January 31, 2017 2:59 PM
> To: qemu-devel@nongnu.org
> Cc: pbonzini@redhat.com; dovgaluk@ispras.ru; kraxel@redhat.com
> Subject: [PATCH] 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.
> 
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> ---
>  audio/audio.c            |   11 +++++-
>  audio/audio.h            |    5 +++
>  audio/mixeng.c           |   31 ++++++++++++++++++
>  docs/replay.txt          |    7 ++++
>  include/sysemu/replay.h  |    7 ++++
>  replay/Makefile.objs     |    1 +
>  replay/replay-audio.c    |   79 ++++++++++++++++++++++++++++++++++++++++++++++
>  replay/replay-internal.h |    4 ++
>  8 files changed, 142 insertions(+), 3 deletions(-)
>  create mode 100644 replay/replay-audio.c
> 
> diff --git a/audio/audio.c b/audio/audio.c
> index 1ee95a5..79c0788 100644
> --- a/audio/audio.c
> +++ b/audio/audio.c
> @@ -28,6 +28,7 @@
>  #include "qemu/timer.h"
>  #include "sysemu/sysemu.h"
>  #include "qemu/cutils.h"
> +#include "sysemu/replay.h"
> 
>  #define AUDIO_CAP "audio"
>  #include "audio_int.h"
> @@ -1113,7 +1114,7 @@ static void audio_reset_timer (AudioState *s)
>  {
>      if (audio_is_timer_needed ()) {
>          if (!timer_pending(s->ts)) {
> -            timer_mod (s->ts,
> +            timer_mod(s->ts,
>                  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + conf.period.ticks);
>          }
>      }
> @@ -1389,6 +1390,7 @@ static void audio_run_out (AudioState *s)
> 
>          prev_rpos = hw->rpos;
>          played = hw->pcm_ops->run_out (hw, live);
> +        replay_audio_out(&played);
>          if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
>              dolog ("hw->rpos=%d hw->samples=%d played=%d\n",
>                     hw->rpos, hw->samples, played);
> @@ -1452,9 +1454,12 @@ static void audio_run_in (AudioState *s)
> 
>      while ((hw = audio_pcm_hw_find_any_enabled_in (hw))) {
>          SWVoiceIn *sw;
> -        int captured, min;
> +        int captured = 0, min;
> 
> -        captured = hw->pcm_ops->run_in (hw);
> +        if (replay_mode != REPLAY_MODE_PLAY) {
> +            captured = hw->pcm_ops->run_in(hw);
> +        }
> +        replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples);
> 
>          min = audio_pcm_hw_find_min_in (hw);
>          hw->total_samples_captured += captured - min;
> diff --git a/audio/audio.h b/audio/audio.h
> index c3c5198..f4339a1 100644
> --- a/audio/audio.h
> +++ b/audio/audio.h
> @@ -166,4 +166,9 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
>  bool audio_is_cleaning_up(void);
>  void audio_cleanup(void);
> 
> +void audio_sample_to_uint64(void *samples, int pos,
> +                            uint64_t *left, uint64_t *right);
> +void audio_sample_from_uint64(void *samples, int pos,
> +                            uint64_t left, uint64_t right);
> +
>  #endif /* QEMU_AUDIO_H */
> diff --git a/audio/mixeng.c b/audio/mixeng.c
> index 66c0328..c23508e 100644
> --- a/audio/mixeng.c
> +++ b/audio/mixeng.c
> @@ -267,6 +267,37 @@ f_sample *mixeng_clip[2][2][2][3] = {
>      }
>  };
> 
> +
> +void audio_sample_to_uint64(void *samples, int pos,
> +                            uint64_t *left, uint64_t *right)
> +{
> +    struct st_sample *sample = samples;
> +    sample += pos;
> +#ifdef FLOAT_MIXENG
> +    error_report(
> +        "Coreaudio and floating point samples are not supported by replay yet");
> +    abort();
> +#else
> +    *left = sample->l;
> +    *right = sample->r;
> +#endif
> +}
> +
> +void audio_sample_from_uint64(void *samples, int pos,
> +                            uint64_t left, uint64_t right)
> +{
> +    struct st_sample *sample = samples;
> +    sample += pos;
> +#ifdef FLOAT_MIXENG
> +    error_report(
> +        "Coreaudio and floating point samples are not supported by replay yet");
> +    abort();
> +#else
> +    sample->l = left;
> +    sample->r = right;
> +#endif
> +}
> +
>  /*
>   * August 21, 1998
>   * Copyright 1998 Fabrice Bellard.
> diff --git a/docs/replay.txt b/docs/replay.txt
> index 03e1931..486c1e0 100644
> --- a/docs/replay.txt
> +++ b/docs/replay.txt
> @@ -225,3 +225,10 @@ recording the virtual machine this filter puts all packets coming from
>  the outer world into the log. In replay mode packets from the log are
>  injected into the network device. All interactions with network backend
>  in replay mode are disabled.
> +
> +Audio devices
> +-------------
> +
> +Audio data is recorded and replay automatically. The command line for recording
> +and replaying must contain identical specifications of audio hardware, e.g.:
> + -soundhw ac97
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index 7aad20b..f1c0712 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -152,6 +152,13 @@ void replay_unregister_net(ReplayNetState *rns);
>  void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
>                               const struct iovec *iov, int iovcnt);
> 
> +/* Audio */
> +
> +/*! Saves/restores number of played samples of audio out operation. */
> +void replay_audio_out(int *played);
> +/*! Saves/restores recorded samples of audio in operation. */
> +void replay_audio_in(int *recorded, void *samples, int *wpos, int size);
> +
>  /* VM state operations */
> 
>  /*! Called at the start of execution.
> diff --git a/replay/Makefile.objs b/replay/Makefile.objs
> index b2afd40..cee6539 100644
> --- a/replay/Makefile.objs
> +++ b/replay/Makefile.objs
> @@ -6,3 +6,4 @@ common-obj-y += replay-input.o
>  common-obj-y += replay-char.o
>  common-obj-y += replay-snapshot.o
>  common-obj-y += replay-net.o
> +common-obj-y += replay-audio.o
> \ No newline at end of file
> diff --git a/replay/replay-audio.c b/replay/replay-audio.c
> new file mode 100644
> index 0000000..3d83743
> --- /dev/null
> +++ b/replay/replay-audio.c
> @@ -0,0 +1,79 @@
> +/*
> + * replay-audio.c
> + *
> + * Copyright (c) 2010-2017 Institute for System Programming
> + *                         of the Russian Academy of Sciences.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "sysemu/replay.h"
> +#include "replay-internal.h"
> +#include "sysemu/sysemu.h"
> +#include "audio/audio.h"
> +
> +void replay_audio_out(int *played)
> +{
> +    if (replay_mode == REPLAY_MODE_RECORD) {
> +        replay_save_instructions();
> +        replay_mutex_lock();
> +        replay_put_event(EVENT_AUDIO_OUT);
> +        replay_put_dword(*played);
> +        replay_mutex_unlock();
> +    } else if (replay_mode == REPLAY_MODE_PLAY) {
> +        replay_account_executed_instructions();
> +        replay_mutex_lock();
> +        if (replay_next_event_is(EVENT_AUDIO_OUT)) {
> +            *played = replay_get_dword();
> +            replay_finish_event();
> +            replay_mutex_unlock();
> +        } else {
> +            replay_mutex_unlock();
> +            error_report("Missing audio out event in the replay log");
> +            abort();
> +        }
> +    }
> +}
> +
> +void replay_audio_in(int *recorded, void *samples, int *wpos, int size)
> +{
> +    int pos;
> +    uint64_t left, right;
> +    if (replay_mode == REPLAY_MODE_RECORD) {
> +        replay_save_instructions();
> +        replay_mutex_lock();
> +        replay_put_event(EVENT_AUDIO_IN);
> +        replay_put_dword(*recorded);
> +        replay_put_dword(*wpos);
> +        for (pos = (*wpos - *recorded + size) % size ; pos != *wpos
> +             ; pos = (pos + 1) % size) {
> +            audio_sample_to_uint64(samples, pos, &left, &right);
> +            replay_put_qword(left);
> +            replay_put_qword(right);
> +        }
> +        replay_mutex_unlock();
> +    } else if (replay_mode == REPLAY_MODE_PLAY) {
> +        replay_account_executed_instructions();
> +        replay_mutex_lock();
> +        if (replay_next_event_is(EVENT_AUDIO_IN)) {
> +            *recorded = replay_get_dword();
> +            *wpos = replay_get_dword();
> +            for (pos = (*wpos - *recorded + size) % size ; pos != *wpos
> +                 ; pos = (pos + 1) % size) {
> +                left = replay_get_qword();
> +                right = replay_get_qword();
> +                audio_sample_from_uint64(samples, pos, left, right);
> +            }
> +            replay_finish_event();
> +            replay_mutex_unlock();
> +        } else {
> +            replay_mutex_unlock();
> +            error_report("Missing audio in event in the replay log");
> +            abort();
> +        }
> +    }
> +}
> diff --git a/replay/replay-internal.h b/replay/replay-internal.h
> index c26d079..ed66ed8 100644
> --- a/replay/replay-internal.h
> +++ b/replay/replay-internal.h
> @@ -29,6 +29,10 @@ enum ReplayEvents {
>      /* for character device read all event */
>      EVENT_CHAR_READ_ALL,
>      EVENT_CHAR_READ_ALL_ERROR,
> +    /* for audio out event */
> +    EVENT_AUDIO_OUT,
> +    /* for audio in event */
> +    EVENT_AUDIO_IN,
>      /* for clock read/writes */
>      /* some of greater codes are reserved for clocks */
>      EVENT_CLOCK,

      parent reply	other threads:[~2017-02-13  5:05 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-31 11:59 [Qemu-devel] [PATCH] replay: add record/replay for audio passthrough Pavel Dovgalyuk
2017-02-01 13:23 ` Gerd Hoffmann
2017-02-13  5:04 ` Pavel Dovgalyuk [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='000e01d285b6$b7073290$251597b0$@ru' \
    --to=dovgaluk@ispras.ru \
    --cc=kraxel@redhat.com \
    --cc=pavel.dovgaluk@ispras.ru \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).